提交 05ec7dd8 编写于 作者: L Linus Torvalds

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6: (154 commits)
  mtd: cfi_cmdset_0002: use AMD standard command-set with Winbond flash chips
  mtd: cfi_cmdset_0002: Fix MODULE_ALIAS and linkage for new 0701 commandset ID
  mtd: mxc_nand: Remove duplicate NAND_CMD_RESET case value
  mtd: update gfp/slab.h includes
  jffs2: Stop triggering block erases from jffs2_write_super()
  jffs2: Rename jffs2_erase_pending_trigger() to jffs2_dirty_trigger()
  jffs2: Use jffs2_garbage_collect_trigger() to trigger pending erases
  jffs2: Require jffs2_garbage_collect_trigger() to be called with lock held
  jffs2: Wake GC thread when there are blocks to be erased
  jffs2: Erase pending blocks in GC pass, avoid invalid -EIO return
  jffs2: Add 'work_done' return value from jffs2_erase_pending_blocks()
  mtd: mtdchar: Do not corrupt backing device of device node inode
  mtd/maps/pcmciamtd: Fix printk format for ssize_t in debug messages
  drivers/mtd: Use kmemdup
  mtd: cfi_cmdset_0002: Fix argument order in bootloc warning
  mtd: nand: add Toshiba TC58NVG0 device ID
  pcmciamtd: add another ID
  pcmciamtd: coding style cleanups
  pcmciamtd: fixing obvious errors
  mtd: chips: add SST39WF160x NOR-flashes
  ...

Trivial conflicts due to dev_node removal in drivers/mtd/maps/pcmciamtd.c
...@@ -4762,6 +4762,12 @@ S: Maintained ...@@ -4762,6 +4762,12 @@ S: Maintained
F: Documentation/rfkill.txt F: Documentation/rfkill.txt
F: net/rfkill/ F: net/rfkill/
RICOH SMARTMEDIA/XD DRIVER
M: Maxim Levitsky <maximlevitsky@gmail.com>
S: Maintained
F: drivers/mtd/nand/r822.c
F: drivers/mtd/nand/r822.h
RISCOM8 DRIVER RISCOM8 DRIVER
S: Orphan S: Orphan
F: Documentation/serial/riscom8.txt F: Documentation/serial/riscom8.txt
......
...@@ -9,9 +9,6 @@ ...@@ -9,9 +9,6 @@
* febff000 22000000 4K model number register * febff000 22000000 4K model number register
* febfe000 22400000 4K options register * febfe000 22400000 4K options register
* febfd000 22800000 4K options register #2 * febfd000 22800000 4K options register #2
* febfc000 [67]0000000 4K NAND data register
* febfb000 [67]0400000 4K NAND control register
* febfa000 [67]0800000 4K NAND busy register
* febf9000 10800000 4K TS-5620 RTC index register * febf9000 10800000 4K TS-5620 RTC index register
* febf8000 11700000 4K TS-5620 RTC data register * febf8000 11700000 4K TS-5620 RTC data register
*/ */
...@@ -41,22 +38,6 @@ ...@@ -41,22 +38,6 @@
#define TS72XX_OPTIONS2_TS9420_BOOT 0x02 #define TS72XX_OPTIONS2_TS9420_BOOT 0x02
#define TS72XX_NAND1_DATA_PHYS_BASE 0x60000000
#define TS72XX_NAND2_DATA_PHYS_BASE 0x70000000
#define TS72XX_NAND_DATA_VIRT_BASE 0xfebfc000
#define TS72XX_NAND_DATA_SIZE 0x00001000
#define TS72XX_NAND1_CONTROL_PHYS_BASE 0x60400000
#define TS72XX_NAND2_CONTROL_PHYS_BASE 0x70400000
#define TS72XX_NAND_CONTROL_VIRT_BASE 0xfebfb000
#define TS72XX_NAND_CONTROL_SIZE 0x00001000
#define TS72XX_NAND1_BUSY_PHYS_BASE 0x60800000
#define TS72XX_NAND2_BUSY_PHYS_BASE 0x70800000
#define TS72XX_NAND_BUSY_VIRT_BASE 0xfebfa000
#define TS72XX_NAND_BUSY_SIZE 0x00001000
#define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000 #define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000
#define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000 #define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000
#define TS72XX_RTC_INDEX_SIZE 0x00001000 #define TS72XX_RTC_INDEX_SIZE 0x00001000
......
...@@ -10,12 +10,16 @@ ...@@ -10,12 +10,16 @@
* your option) any later version. * your option) any later version.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/m48t86.h> #include <linux/m48t86.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/ts72xx.h> #include <mach/ts72xx.h>
...@@ -54,92 +58,162 @@ static struct map_desc ts72xx_io_desc[] __initdata = { ...@@ -54,92 +58,162 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
} }
}; };
static struct map_desc ts72xx_nand_io_desc[] __initdata = { static void __init ts72xx_map_io(void)
{ {
.virtual = TS72XX_NAND_DATA_VIRT_BASE, ep93xx_map_io();
.pfn = __phys_to_pfn(TS72XX_NAND1_DATA_PHYS_BASE), iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
.length = TS72XX_NAND_DATA_SIZE, }
.type = MT_DEVICE,
}, {
.virtual = TS72XX_NAND_CONTROL_VIRT_BASE, /*************************************************************************
.pfn = __phys_to_pfn(TS72XX_NAND1_CONTROL_PHYS_BASE), * NAND flash
.length = TS72XX_NAND_CONTROL_SIZE, *************************************************************************/
.type = MT_DEVICE, #define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */
}, { #define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */
.virtual = TS72XX_NAND_BUSY_VIRT_BASE,
.pfn = __phys_to_pfn(TS72XX_NAND1_BUSY_PHYS_BASE), static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
.length = TS72XX_NAND_BUSY_SIZE, int cmd, unsigned int ctrl)
.type = MT_DEVICE, {
struct nand_chip *chip = mtd->priv;
if (ctrl & NAND_CTRL_CHANGE) {
void __iomem *addr = chip->IO_ADDR_R;
unsigned char bits;
addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
bits = __raw_readb(addr) & ~0x07;
bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */
bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */
bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */
__raw_writeb(bits, addr);
} }
};
static struct map_desc ts72xx_alternate_nand_io_desc[] __initdata = { if (cmd != NAND_CMD_NONE)
__raw_writeb(cmd, chip->IO_ADDR_W);
}
static int ts72xx_nand_device_ready(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
void __iomem *addr = chip->IO_ADDR_R;
addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
return !!(__raw_readb(addr) & 0x20);
}
static const char *ts72xx_nand_part_probes[] = { "cmdlinepart", NULL };
#define TS72XX_BOOTROM_PART_SIZE (SZ_16K)
#define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M)
static struct mtd_partition ts72xx_nand_parts[] = {
{ {
.virtual = TS72XX_NAND_DATA_VIRT_BASE, .name = "TS-BOOTROM",
.pfn = __phys_to_pfn(TS72XX_NAND2_DATA_PHYS_BASE), .offset = 0,
.length = TS72XX_NAND_DATA_SIZE, .size = TS72XX_BOOTROM_PART_SIZE,
.type = MT_DEVICE, .mask_flags = MTD_WRITEABLE, /* force read-only */
}, { }, {
.virtual = TS72XX_NAND_CONTROL_VIRT_BASE, .name = "Linux",
.pfn = __phys_to_pfn(TS72XX_NAND2_CONTROL_PHYS_BASE), .offset = MTDPART_OFS_APPEND,
.length = TS72XX_NAND_CONTROL_SIZE, .size = 0, /* filled in later */
.type = MT_DEVICE,
}, { }, {
.virtual = TS72XX_NAND_BUSY_VIRT_BASE, .name = "RedBoot",
.pfn = __phys_to_pfn(TS72XX_NAND2_BUSY_PHYS_BASE), .offset = MTDPART_OFS_APPEND,
.length = TS72XX_NAND_BUSY_SIZE, .size = MTDPART_SIZ_FULL,
.type = MT_DEVICE, .mask_flags = MTD_WRITEABLE, /* force read-only */
} },
}; };
static void __init ts72xx_map_io(void) static void ts72xx_nand_set_parts(uint64_t size,
struct platform_nand_chip *chip)
{ {
ep93xx_map_io(); /* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); if (size == SZ_32M || size == SZ_128M) {
/* Set the "Linux" partition size */
ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
/* chip->partitions = ts72xx_nand_parts;
* The TS-7200 has NOR flash, the other models have NAND flash. chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
*/ } else {
if (!board_is_ts7200()) { pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
if (is_ts9420_installed()) {
iotable_init(ts72xx_alternate_nand_io_desc,
ARRAY_SIZE(ts72xx_alternate_nand_io_desc));
} else {
iotable_init(ts72xx_nand_io_desc,
ARRAY_SIZE(ts72xx_nand_io_desc));
}
} }
} }
static struct platform_nand_data ts72xx_nand_data = {
.chip = {
.nr_chips = 1,
.chip_offset = 0,
.chip_delay = 15,
.part_probe_types = ts72xx_nand_part_probes,
.set_parts = ts72xx_nand_set_parts,
},
.ctrl = {
.cmd_ctrl = ts72xx_nand_hwcontrol,
.dev_ready = ts72xx_nand_device_ready,
},
};
static struct resource ts72xx_nand_resource[] = {
{
.start = 0, /* filled in later */
.end = 0, /* filled in later */
.flags = IORESOURCE_MEM,
},
};
static struct platform_device ts72xx_nand_flash = {
.name = "gen_nand",
.id = -1,
.dev.platform_data = &ts72xx_nand_data,
.resource = ts72xx_nand_resource,
.num_resources = ARRAY_SIZE(ts72xx_nand_resource),
};
/************************************************************************* /*************************************************************************
* NOR flash (TS-7200 only) * NOR flash (TS-7200 only)
*************************************************************************/ *************************************************************************/
static struct physmap_flash_data ts72xx_flash_data = { static struct physmap_flash_data ts72xx_nor_data = {
.width = 2, .width = 2,
}; };
static struct resource ts72xx_flash_resource = { static struct resource ts72xx_nor_resource = {
.start = EP93XX_CS6_PHYS_BASE, .start = EP93XX_CS6_PHYS_BASE,
.end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1, .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}; };
static struct platform_device ts72xx_flash = { static struct platform_device ts72xx_nor_flash = {
.name = "physmap-flash", .name = "physmap-flash",
.id = 0, .id = 0,
.dev = { .dev.platform_data = &ts72xx_nor_data,
.platform_data = &ts72xx_flash_data, .resource = &ts72xx_nor_resource,
}, .num_resources = 1,
.num_resources = 1,
.resource = &ts72xx_flash_resource,
}; };
static void __init ts72xx_register_flash(void) static void __init ts72xx_register_flash(void)
{ {
if (board_is_ts7200()) if (board_is_ts7200()) {
platform_device_register(&ts72xx_flash); platform_device_register(&ts72xx_nor_flash);
} else {
resource_size_t start;
if (is_ts9420_installed())
start = EP93XX_CS7_PHYS_BASE;
else
start = EP93XX_CS6_PHYS_BASE;
ts72xx_nand_resource[0].start = start;
ts72xx_nand_resource[0].end = start + SZ_16M - 1;
platform_device_register(&ts72xx_nand_flash);
}
} }
static unsigned char ts72xx_rtc_readbyte(unsigned long addr) static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
{ {
__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
......
...@@ -305,6 +305,15 @@ void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, ...@@ -305,6 +305,15 @@ void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
platform_device_register(&kirkwood_nand_flash); platform_device_register(&kirkwood_nand_flash);
} }
void __init kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
int (*dev_ready)(struct mtd_info *))
{
kirkwood_clk_ctrl |= CGC_RUNIT;
kirkwood_nand_data.parts = parts;
kirkwood_nand_data.nr_parts = nr_parts;
kirkwood_nand_data.dev_ready = dev_ready;
platform_device_register(&kirkwood_nand_flash);
}
/***************************************************************************** /*****************************************************************************
* SoC RTC * SoC RTC
......
...@@ -16,6 +16,7 @@ struct mv643xx_eth_platform_data; ...@@ -16,6 +16,7 @@ struct mv643xx_eth_platform_data;
struct mv_sata_platform_data; struct mv_sata_platform_data;
struct mvsdio_platform_data; struct mvsdio_platform_data;
struct mtd_partition; struct mtd_partition;
struct mtd_info;
/* /*
* Basic Kirkwood init functions used early by machine-setup. * Basic Kirkwood init functions used early by machine-setup.
...@@ -41,6 +42,7 @@ void kirkwood_i2c_init(void); ...@@ -41,6 +42,7 @@ void kirkwood_i2c_init(void);
void kirkwood_uart0_init(void); void kirkwood_uart0_init(void);
void kirkwood_uart1_init(void); void kirkwood_uart1_init(void);
void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay); void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev_ready)(struct mtd_info *));
extern int kirkwood_tclk; extern int kirkwood_tclk;
extern struct sys_timer kirkwood_timer; extern struct sys_timer kirkwood_timer;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
*/ */
struct orion_nand_data { struct orion_nand_data {
struct mtd_partition *parts; struct mtd_partition *parts;
int (*dev_ready)(struct mtd_info *mtd);
u32 nr_parts; u32 nr_parts;
u8 ale; /* address line number connected to ALE */ u8 ale; /* address line number connected to ALE */
u8 cle; /* address line number connected to CLE */ u8 cle; /* address line number connected to CLE */
......
...@@ -304,6 +304,19 @@ config SSFDC ...@@ -304,6 +304,19 @@ config SSFDC
This enables read only access to SmartMedia formatted NAND This enables read only access to SmartMedia formatted NAND
flash. You can mount it with FAT file system. flash. You can mount it with FAT file system.
config SM_FTL
tristate "SmartMedia/xD new translation layer"
depends on EXPERIMENTAL && BLOCK
select MTD_BLKDEVS
select MTD_NAND_ECC
help
This enables new and very EXPERMENTAL support for SmartMedia/xD
FTL (Flash translation layer).
Write support isn't yet well tested, therefore this code IS likely to
eat your card, so please don't use it together with valuable data.
Use readonly driver (CONFIG_SSFDC) instead.
config MTD_OOPS config MTD_OOPS
tristate "Log panic/oops to an MTD buffer" tristate "Log panic/oops to an MTD buffer"
depends on MTD depends on MTD
......
...@@ -24,6 +24,7 @@ obj-$(CONFIG_NFTL) += nftl.o ...@@ -24,6 +24,7 @@ obj-$(CONFIG_NFTL) += nftl.o
obj-$(CONFIG_INFTL) += inftl.o obj-$(CONFIG_INFTL) += inftl.o
obj-$(CONFIG_RFD_FTL) += rfd_ftl.o obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
obj-$(CONFIG_SSFDC) += ssfdc.o obj-$(CONFIG_SSFDC) += ssfdc.o
obj-$(CONFIG_SM_FTL) += sm_ftl.o
obj-$(CONFIG_MTD_OOPS) += mtdoops.o obj-$(CONFIG_MTD_OOPS) += mtdoops.o
nftl-objs := nftlcore.o nftlmount.o nftl-objs := nftlcore.o nftlmount.o
......
...@@ -615,10 +615,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) ...@@ -615,10 +615,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
return mtd; return mtd;
setup_err: setup_err:
if(mtd) { kfree(mtd->eraseregions);
kfree(mtd->eraseregions); kfree(mtd);
kfree(mtd);
}
kfree(cfi->cmdset_priv); kfree(cfi->cmdset_priv);
return NULL; return NULL;
} }
...@@ -727,8 +725,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, ...@@ -727,8 +725,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
/* those should be reset too since /* those should be reset too since
they create memory references. */ they create memory references. */
init_waitqueue_head(&chip->wq); init_waitqueue_head(&chip->wq);
spin_lock_init(&chip->_spinlock); mutex_init(&chip->mutex);
chip->mutex = &chip->_spinlock;
chip++; chip++;
} }
} }
...@@ -774,9 +771,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long ...@@ -774,9 +771,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS)) if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS))
break; break;
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
/* Someone else might have been playing with it. */ /* Someone else might have been playing with it. */
return -EAGAIN; return -EAGAIN;
} }
...@@ -823,9 +820,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long ...@@ -823,9 +820,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
return -EIO; return -EIO;
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
/* Nobody will touch it while it's in state FL_ERASE_SUSPENDING. /* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
So we can just loop here. */ So we can just loop here. */
} }
...@@ -852,10 +849,10 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long ...@@ -852,10 +849,10 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
sleep: sleep:
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
return -EAGAIN; return -EAGAIN;
} }
} }
...@@ -901,20 +898,20 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr ...@@ -901,20 +898,20 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
* it'll happily send us to sleep. In any case, when * it'll happily send us to sleep. In any case, when
* get_chip returns success we're clear to go ahead. * get_chip returns success we're clear to go ahead.
*/ */
ret = spin_trylock(contender->mutex); ret = mutex_trylock(&contender->mutex);
spin_unlock(&shared->lock); spin_unlock(&shared->lock);
if (!ret) if (!ret)
goto retry; goto retry;
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
ret = chip_ready(map, contender, contender->start, mode); ret = chip_ready(map, contender, contender->start, mode);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
goto retry; goto retry;
} }
if (ret) { if (ret) {
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
return ret; return ret;
} }
spin_lock(&shared->lock); spin_lock(&shared->lock);
...@@ -923,10 +920,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr ...@@ -923,10 +920,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
* in FL_SYNCING state. Put contender and retry. */ * in FL_SYNCING state. Put contender and retry. */
if (chip->state == FL_SYNCING) { if (chip->state == FL_SYNCING) {
put_chip(map, contender, contender->start); put_chip(map, contender, contender->start);
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
goto retry; goto retry;
} }
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
} }
/* Check if we already have suspended erase /* Check if we already have suspended erase
...@@ -936,10 +933,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr ...@@ -936,10 +933,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
spin_unlock(&shared->lock); spin_unlock(&shared->lock);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
goto retry; goto retry;
} }
...@@ -969,12 +966,12 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad ...@@ -969,12 +966,12 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
if (shared->writing && shared->writing != chip) { if (shared->writing && shared->writing != chip) {
/* give back ownership to who we loaned it from */ /* give back ownership to who we loaned it from */
struct flchip *loaner = shared->writing; struct flchip *loaner = shared->writing;
spin_lock(loaner->mutex); mutex_lock(&loaner->mutex);
spin_unlock(&shared->lock); spin_unlock(&shared->lock);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
put_chip(map, loaner, loaner->start); put_chip(map, loaner, loaner->start);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
spin_unlock(loaner->mutex); mutex_unlock(&loaner->mutex);
wake_up(&chip->wq); wake_up(&chip->wq);
return; return;
} }
...@@ -1144,7 +1141,7 @@ static int __xipram xip_wait_for_operation( ...@@ -1144,7 +1141,7 @@ static int __xipram xip_wait_for_operation(
(void) map_read(map, adr); (void) map_read(map, adr);
xip_iprefetch(); xip_iprefetch();
local_irq_enable(); local_irq_enable();
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
xip_iprefetch(); xip_iprefetch();
cond_resched(); cond_resched();
...@@ -1154,15 +1151,15 @@ static int __xipram xip_wait_for_operation( ...@@ -1154,15 +1151,15 @@ static int __xipram xip_wait_for_operation(
* a suspended erase state. If so let's wait * a suspended erase state. If so let's wait
* until it's done. * until it's done.
*/ */
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
while (chip->state != newstate) { while (chip->state != newstate) {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
} }
/* Disallow XIP again */ /* Disallow XIP again */
local_irq_disable(); local_irq_disable();
...@@ -1218,10 +1215,10 @@ static int inval_cache_and_wait_for_operation( ...@@ -1218,10 +1215,10 @@ static int inval_cache_and_wait_for_operation(
int chip_state = chip->state; int chip_state = chip->state;
unsigned int timeo, sleep_time, reset_timeo; unsigned int timeo, sleep_time, reset_timeo;
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
if (inval_len) if (inval_len)
INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
timeo = chip_op_time_max; timeo = chip_op_time_max;
if (!timeo) if (!timeo)
...@@ -1241,7 +1238,7 @@ static int inval_cache_and_wait_for_operation( ...@@ -1241,7 +1238,7 @@ static int inval_cache_and_wait_for_operation(
} }
/* OK Still waiting. Drop the lock, wait a while and retry. */ /* OK Still waiting. Drop the lock, wait a while and retry. */
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
if (sleep_time >= 1000000/HZ) { if (sleep_time >= 1000000/HZ) {
/* /*
* Half of the normal delay still remaining * Half of the normal delay still remaining
...@@ -1256,17 +1253,17 @@ static int inval_cache_and_wait_for_operation( ...@@ -1256,17 +1253,17 @@ static int inval_cache_and_wait_for_operation(
cond_resched(); cond_resched();
timeo--; timeo--;
} }
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
while (chip->state != chip_state) { while (chip->state != chip_state) {
/* Someone's suspended the operation: sleep */ /* Someone's suspended the operation: sleep */
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
} }
if (chip->erase_suspended && chip_state == FL_ERASING) { if (chip->erase_suspended && chip_state == FL_ERASING) {
/* Erase suspend occured while sleep: reset timeout */ /* Erase suspend occured while sleep: reset timeout */
...@@ -1302,7 +1299,7 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a ...@@ -1302,7 +1299,7 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a
/* Ensure cmd read/writes are aligned. */ /* Ensure cmd read/writes are aligned. */
cmd_addr = adr & ~(map_bankwidth(map)-1); cmd_addr = adr & ~(map_bankwidth(map)-1);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, cmd_addr, FL_POINT); ret = get_chip(map, chip, cmd_addr, FL_POINT);
...@@ -1313,7 +1310,7 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a ...@@ -1313,7 +1310,7 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a
chip->state = FL_POINT; chip->state = FL_POINT;
chip->ref_point_counter++; chip->ref_point_counter++;
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1398,7 +1395,7 @@ static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) ...@@ -1398,7 +1395,7 @@ static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
else else
thislen = len; thislen = len;
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
if (chip->state == FL_POINT) { if (chip->state == FL_POINT) {
chip->ref_point_counter--; chip->ref_point_counter--;
if(chip->ref_point_counter == 0) if(chip->ref_point_counter == 0)
...@@ -1407,7 +1404,7 @@ static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) ...@@ -1407,7 +1404,7 @@ static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
printk(KERN_ERR "%s: Warning: unpoint called on non pointed region\n", map->name); /* Should this give an error? */ printk(KERN_ERR "%s: Warning: unpoint called on non pointed region\n", map->name); /* Should this give an error? */
put_chip(map, chip, chip->start); put_chip(map, chip, chip->start);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
len -= thislen; len -= thislen;
ofs = 0; ofs = 0;
...@@ -1426,10 +1423,10 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof ...@@ -1426,10 +1423,10 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
/* Ensure cmd read/writes are aligned. */ /* Ensure cmd read/writes are aligned. */
cmd_addr = adr & ~(map_bankwidth(map)-1); cmd_addr = adr & ~(map_bankwidth(map)-1);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, cmd_addr, FL_READY); ret = get_chip(map, chip, cmd_addr, FL_READY);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1443,7 +1440,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof ...@@ -1443,7 +1440,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
put_chip(map, chip, cmd_addr); put_chip(map, chip, cmd_addr);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return 0; return 0;
} }
...@@ -1506,10 +1503,10 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, ...@@ -1506,10 +1503,10 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
return -EINVAL; return -EINVAL;
} }
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, adr, mode); ret = get_chip(map, chip, adr, mode);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1555,7 +1552,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, ...@@ -1555,7 +1552,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
xip_enable(map, chip, adr); xip_enable(map, chip, adr);
out: put_chip(map, chip, adr); out: put_chip(map, chip, adr);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1664,10 +1661,10 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -1664,10 +1661,10 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
/* Let's determine this according to the interleave only once */ /* Let's determine this according to the interleave only once */
write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, cmd_adr, FL_WRITING); ret = get_chip(map, chip, cmd_adr, FL_WRITING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1798,7 +1795,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -1798,7 +1795,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
xip_enable(map, chip, cmd_adr); xip_enable(map, chip, cmd_adr);
out: put_chip(map, chip, cmd_adr); out: put_chip(map, chip, cmd_adr);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1877,10 +1874,10 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1877,10 +1874,10 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
adr += chip->start; adr += chip->start;
retry: retry:
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, adr, FL_ERASING); ret = get_chip(map, chip, adr, FL_ERASING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1936,7 +1933,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1936,7 +1933,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
} else if (chipstatus & 0x20 && retries--) { } else if (chipstatus & 0x20 && retries--) {
printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus); printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus);
put_chip(map, chip, adr); put_chip(map, chip, adr);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
goto retry; goto retry;
} else { } else {
printk(KERN_ERR "%s: block erase failed at 0x%08lx (status 0x%lx)\n", map->name, adr, chipstatus); printk(KERN_ERR "%s: block erase failed at 0x%08lx (status 0x%lx)\n", map->name, adr, chipstatus);
...@@ -1948,7 +1945,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1948,7 +1945,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
xip_enable(map, chip, adr); xip_enable(map, chip, adr);
out: put_chip(map, chip, adr); out: put_chip(map, chip, adr);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -1981,7 +1978,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd) ...@@ -1981,7 +1978,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd)
for (i=0; !ret && i<cfi->numchips; i++) { for (i=0; !ret && i<cfi->numchips; i++) {
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, chip->start, FL_SYNCING); ret = get_chip(map, chip, chip->start, FL_SYNCING);
if (!ret) { if (!ret) {
...@@ -1992,7 +1989,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd) ...@@ -1992,7 +1989,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd)
* with the chip now anyway. * with the chip now anyway.
*/ */
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
} }
/* Unlock the chips again */ /* Unlock the chips again */
...@@ -2000,14 +1997,14 @@ static void cfi_intelext_sync (struct mtd_info *mtd) ...@@ -2000,14 +1997,14 @@ static void cfi_intelext_sync (struct mtd_info *mtd)
for (i--; i >=0; i--) { for (i--; i >=0; i--) {
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
if (chip->state == FL_SYNCING) { if (chip->state == FL_SYNCING) {
chip->state = chip->oldstate; chip->state = chip->oldstate;
chip->oldstate = FL_READY; chip->oldstate = FL_READY;
wake_up(&chip->wq); wake_up(&chip->wq);
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
} }
} }
...@@ -2053,10 +2050,10 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip ...@@ -2053,10 +2050,10 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
adr += chip->start; adr += chip->start;
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, adr, FL_LOCKING); ret = get_chip(map, chip, adr, FL_LOCKING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -2090,7 +2087,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip ...@@ -2090,7 +2087,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
xip_enable(map, chip, adr); xip_enable(map, chip, adr);
out: put_chip(map, chip, adr); out: put_chip(map, chip, adr);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -2155,10 +2152,10 @@ do_otp_read(struct map_info *map, struct flchip *chip, u_long offset, ...@@ -2155,10 +2152,10 @@ do_otp_read(struct map_info *map, struct flchip *chip, u_long offset,
struct cfi_private *cfi = map->fldrv_priv; struct cfi_private *cfi = map->fldrv_priv;
int ret; int ret;
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY); ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -2177,7 +2174,7 @@ do_otp_read(struct map_info *map, struct flchip *chip, u_long offset, ...@@ -2177,7 +2174,7 @@ do_otp_read(struct map_info *map, struct flchip *chip, u_long offset,
INVALIDATE_CACHED_RANGE(map, chip->start + offset, size); INVALIDATE_CACHED_RANGE(map, chip->start + offset, size);
put_chip(map, chip, chip->start); put_chip(map, chip, chip->start);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return 0; return 0;
} }
...@@ -2452,7 +2449,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) ...@@ -2452,7 +2449,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
for (i=0; !ret && i<cfi->numchips; i++) { for (i=0; !ret && i<cfi->numchips; i++) {
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
switch (chip->state) { switch (chip->state) {
case FL_READY: case FL_READY:
...@@ -2484,7 +2481,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) ...@@ -2484,7 +2481,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
case FL_PM_SUSPENDED: case FL_PM_SUSPENDED:
break; break;
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
} }
/* Unlock the chips again */ /* Unlock the chips again */
...@@ -2493,7 +2490,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) ...@@ -2493,7 +2490,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
for (i--; i >=0; i--) { for (i--; i >=0; i--) {
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
if (chip->state == FL_PM_SUSPENDED) { if (chip->state == FL_PM_SUSPENDED) {
/* No need to force it into a known state here, /* No need to force it into a known state here,
...@@ -2503,7 +2500,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) ...@@ -2503,7 +2500,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
chip->oldstate = FL_READY; chip->oldstate = FL_READY;
wake_up(&chip->wq); wake_up(&chip->wq);
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
} }
} }
...@@ -2544,7 +2541,7 @@ static void cfi_intelext_resume(struct mtd_info *mtd) ...@@ -2544,7 +2541,7 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
/* Go to known state. Chip may have been power cycled */ /* Go to known state. Chip may have been power cycled */
if (chip->state == FL_PM_SUSPENDED) { if (chip->state == FL_PM_SUSPENDED) {
...@@ -2553,7 +2550,7 @@ static void cfi_intelext_resume(struct mtd_info *mtd) ...@@ -2553,7 +2550,7 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
wake_up(&chip->wq); wake_up(&chip->wq);
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
} }
if ((mtd->flags & MTD_POWERUP_LOCK) if ((mtd->flags & MTD_POWERUP_LOCK)
...@@ -2573,14 +2570,14 @@ static int cfi_intelext_reset(struct mtd_info *mtd) ...@@ -2573,14 +2570,14 @@ static int cfi_intelext_reset(struct mtd_info *mtd)
/* force the completion of any ongoing operation /* force the completion of any ongoing operation
and switch to array mode so any bootloader in and switch to array mode so any bootloader in
flash is accessible for soft reboot. */ flash is accessible for soft reboot. */
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, chip->start, FL_SHUTDOWN); ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
if (!ret) { if (!ret) {
map_write(map, CMD(0xff), chip->start); map_write(map, CMD(0xff), chip->start);
chip->state = FL_SHUTDOWN; chip->state = FL_SHUTDOWN;
put_chip(map, chip, chip->start); put_chip(map, chip, chip->start);
} }
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
} }
return 0; return 0;
......
此差异已折叠。
...@@ -265,7 +265,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof ...@@ -265,7 +265,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
timeo = jiffies + HZ; timeo = jiffies + HZ;
retry: retry:
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* Check that the chip's ready to talk to us. /* Check that the chip's ready to talk to us.
* If it's in FL_ERASING state, suspend it and make it talk now. * If it's in FL_ERASING state, suspend it and make it talk now.
...@@ -296,15 +296,15 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof ...@@ -296,15 +296,15 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
/* make sure we're in 'read status' mode */ /* make sure we're in 'read status' mode */
map_write(map, CMD(0x70), cmd_addr); map_write(map, CMD(0x70), cmd_addr);
chip->state = FL_ERASING; chip->state = FL_ERASING;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "Chip not ready after erase " printk(KERN_ERR "Chip not ready after erase "
"suspended: status = 0x%lx\n", status.x[0]); "suspended: status = 0x%lx\n", status.x[0]);
return -EIO; return -EIO;
} }
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
} }
suspended = 1; suspended = 1;
...@@ -335,13 +335,13 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof ...@@ -335,13 +335,13 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
/* Urgh. Chip not yet ready to talk to us. */ /* Urgh. Chip not yet ready to talk to us. */
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %lx\n", status.x[0]); printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %lx\n", status.x[0]);
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
goto retry; goto retry;
...@@ -351,7 +351,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof ...@@ -351,7 +351,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
someone changes the status */ someone changes the status */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + HZ; timeo = jiffies + HZ;
...@@ -376,7 +376,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof ...@@ -376,7 +376,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
} }
wake_up(&chip->wq); wake_up(&chip->wq);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return 0; return 0;
} }
...@@ -445,7 +445,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -445,7 +445,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
#ifdef DEBUG_CFI_FEATURES #ifdef DEBUG_CFI_FEATURES
printk("%s: chip->state[%d]\n", __func__, chip->state); printk("%s: chip->state[%d]\n", __func__, chip->state);
#endif #endif
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* Check that the chip's ready to talk to us. /* Check that the chip's ready to talk to us.
* Later, we can actually think about interrupting it * Later, we can actually think about interrupting it
...@@ -470,14 +470,14 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -470,14 +470,14 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
break; break;
/* Urgh. Chip not yet ready to talk to us. */ /* Urgh. Chip not yet ready to talk to us. */
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "waiting for chip to be ready timed out in buffer write Xstatus = %lx, status = %lx\n", printk(KERN_ERR "waiting for chip to be ready timed out in buffer write Xstatus = %lx, status = %lx\n",
status.x[0], map_read(map, cmd_adr).x[0]); status.x[0], map_read(map, cmd_adr).x[0]);
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
goto retry; goto retry;
...@@ -486,7 +486,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -486,7 +486,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
someone changes the status */ someone changes the status */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + HZ; timeo = jiffies + HZ;
...@@ -503,16 +503,16 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -503,16 +503,16 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
if (map_word_andequal(map, status, status_OK, status_OK)) if (map_word_andequal(map, status, status_OK, status_OK))
break; break;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
if (++z > 100) { if (++z > 100) {
/* Argh. Not ready for write to buffer */ /* Argh. Not ready for write to buffer */
DISABLE_VPP(map); DISABLE_VPP(map);
map_write(map, CMD(0x70), cmd_adr); map_write(map, CMD(0x70), cmd_adr);
chip->state = FL_STATUS; chip->state = FL_STATUS;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %lx\n", status.x[0]); printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %lx\n", status.x[0]);
return -EIO; return -EIO;
} }
...@@ -532,9 +532,9 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -532,9 +532,9 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
map_write(map, CMD(0xd0), cmd_adr); map_write(map, CMD(0xd0), cmd_adr);
chip->state = FL_WRITING; chip->state = FL_WRITING;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(chip->buffer_write_time); cfi_udelay(chip->buffer_write_time);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
timeo = jiffies + (HZ/2); timeo = jiffies + (HZ/2);
z = 0; z = 0;
...@@ -543,11 +543,11 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -543,11 +543,11 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
/* Someone's suspended the write. Sleep */ /* Someone's suspended the write. Sleep */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + (HZ / 2); /* FIXME */ timeo = jiffies + (HZ / 2); /* FIXME */
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
continue; continue;
} }
...@@ -563,16 +563,16 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -563,16 +563,16 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
map_write(map, CMD(0x70), adr); map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS; chip->state = FL_STATUS;
DISABLE_VPP(map); DISABLE_VPP(map);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n"); printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n");
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
z++; z++;
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
} }
if (!z) { if (!z) {
chip->buffer_write_time--; chip->buffer_write_time--;
...@@ -596,11 +596,11 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -596,11 +596,11 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
/* put back into read status register mode */ /* put back into read status register mode */
map_write(map, CMD(0x70), adr); map_write(map, CMD(0x70), adr);
wake_up(&chip->wq); wake_up(&chip->wq);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return map_word_bitsset(map, status, CMD(0x02)) ? -EROFS : -EIO; return map_word_bitsset(map, status, CMD(0x02)) ? -EROFS : -EIO;
} }
wake_up(&chip->wq); wake_up(&chip->wq);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return 0; return 0;
} }
...@@ -749,7 +749,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -749,7 +749,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
timeo = jiffies + HZ; timeo = jiffies + HZ;
retry: retry:
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* Check that the chip's ready to talk to us. */ /* Check that the chip's ready to talk to us. */
switch (chip->state) { switch (chip->state) {
...@@ -766,13 +766,13 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -766,13 +766,13 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
/* Urgh. Chip not yet ready to talk to us. */ /* Urgh. Chip not yet ready to talk to us. */
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "waiting for chip to be ready timed out in erase\n"); printk(KERN_ERR "waiting for chip to be ready timed out in erase\n");
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
goto retry; goto retry;
...@@ -781,7 +781,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -781,7 +781,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
someone changes the status */ someone changes the status */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + HZ; timeo = jiffies + HZ;
...@@ -797,9 +797,9 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -797,9 +797,9 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
map_write(map, CMD(0xD0), adr); map_write(map, CMD(0xD0), adr);
chip->state = FL_ERASING; chip->state = FL_ERASING;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
msleep(1000); msleep(1000);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* FIXME. Use a timer to check this, and return immediately. */ /* FIXME. Use a timer to check this, and return immediately. */
/* Once the state machine's known to be working I'll do that */ /* Once the state machine's known to be working I'll do that */
...@@ -810,11 +810,11 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -810,11 +810,11 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
/* Someone's suspended the erase. Sleep */ /* Someone's suspended the erase. Sleep */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + (HZ*20); /* FIXME */ timeo = jiffies + (HZ*20); /* FIXME */
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
continue; continue;
} }
...@@ -828,14 +828,14 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -828,14 +828,14 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
chip->state = FL_STATUS; chip->state = FL_STATUS;
printk(KERN_ERR "waiting for erase to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]); printk(KERN_ERR "waiting for erase to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
DISABLE_VPP(map); DISABLE_VPP(map);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
} }
DISABLE_VPP(map); DISABLE_VPP(map);
...@@ -878,7 +878,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -878,7 +878,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, chipstatus); printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, chipstatus);
timeo = jiffies + HZ; timeo = jiffies + HZ;
chip->state = FL_STATUS; chip->state = FL_STATUS;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
goto retry; goto retry;
} }
printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus); printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus);
...@@ -887,7 +887,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u ...@@ -887,7 +887,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
} }
wake_up(&chip->wq); wake_up(&chip->wq);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -995,7 +995,7 @@ static void cfi_staa_sync (struct mtd_info *mtd) ...@@ -995,7 +995,7 @@ static void cfi_staa_sync (struct mtd_info *mtd)
chip = &cfi->chips[i]; chip = &cfi->chips[i];
retry: retry:
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
switch(chip->state) { switch(chip->state) {
case FL_READY: case FL_READY:
...@@ -1009,7 +1009,7 @@ static void cfi_staa_sync (struct mtd_info *mtd) ...@@ -1009,7 +1009,7 @@ static void cfi_staa_sync (struct mtd_info *mtd)
* with the chip now anyway. * with the chip now anyway.
*/ */
case FL_SYNCING: case FL_SYNCING:
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
break; break;
default: default:
...@@ -1017,7 +1017,7 @@ static void cfi_staa_sync (struct mtd_info *mtd) ...@@ -1017,7 +1017,7 @@ static void cfi_staa_sync (struct mtd_info *mtd)
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
...@@ -1030,13 +1030,13 @@ static void cfi_staa_sync (struct mtd_info *mtd) ...@@ -1030,13 +1030,13 @@ static void cfi_staa_sync (struct mtd_info *mtd)
for (i--; i >=0; i--) { for (i--; i >=0; i--) {
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
if (chip->state == FL_SYNCING) { if (chip->state == FL_SYNCING) {
chip->state = chip->oldstate; chip->state = chip->oldstate;
wake_up(&chip->wq); wake_up(&chip->wq);
} }
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
} }
} }
...@@ -1054,7 +1054,7 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un ...@@ -1054,7 +1054,7 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un
timeo = jiffies + HZ; timeo = jiffies + HZ;
retry: retry:
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* Check that the chip's ready to talk to us. */ /* Check that the chip's ready to talk to us. */
switch (chip->state) { switch (chip->state) {
...@@ -1071,13 +1071,13 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un ...@@ -1071,13 +1071,13 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un
/* Urgh. Chip not yet ready to talk to us. */ /* Urgh. Chip not yet ready to talk to us. */
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "waiting for chip to be ready timed out in lock\n"); printk(KERN_ERR "waiting for chip to be ready timed out in lock\n");
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
goto retry; goto retry;
...@@ -1086,7 +1086,7 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un ...@@ -1086,7 +1086,7 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un
someone changes the status */ someone changes the status */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + HZ; timeo = jiffies + HZ;
...@@ -1098,9 +1098,9 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un ...@@ -1098,9 +1098,9 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un
map_write(map, CMD(0x01), adr); map_write(map, CMD(0x01), adr);
chip->state = FL_LOCKING; chip->state = FL_LOCKING;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
msleep(1000); msleep(1000);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* FIXME. Use a timer to check this, and return immediately. */ /* FIXME. Use a timer to check this, and return immediately. */
/* Once the state machine's known to be working I'll do that */ /* Once the state machine's known to be working I'll do that */
...@@ -1118,21 +1118,21 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un ...@@ -1118,21 +1118,21 @@ static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, un
chip->state = FL_STATUS; chip->state = FL_STATUS;
printk(KERN_ERR "waiting for lock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]); printk(KERN_ERR "waiting for lock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
DISABLE_VPP(map); DISABLE_VPP(map);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
} }
/* Done and happy. */ /* Done and happy. */
chip->state = FL_STATUS; chip->state = FL_STATUS;
DISABLE_VPP(map); DISABLE_VPP(map);
wake_up(&chip->wq); wake_up(&chip->wq);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return 0; return 0;
} }
static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
...@@ -1203,7 +1203,7 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1203,7 +1203,7 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip,
timeo = jiffies + HZ; timeo = jiffies + HZ;
retry: retry:
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* Check that the chip's ready to talk to us. */ /* Check that the chip's ready to talk to us. */
switch (chip->state) { switch (chip->state) {
...@@ -1220,13 +1220,13 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1220,13 +1220,13 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip,
/* Urgh. Chip not yet ready to talk to us. */ /* Urgh. Chip not yet ready to talk to us. */
if (time_after(jiffies, timeo)) { if (time_after(jiffies, timeo)) {
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
printk(KERN_ERR "waiting for chip to be ready timed out in unlock\n"); printk(KERN_ERR "waiting for chip to be ready timed out in unlock\n");
return -EIO; return -EIO;
} }
/* Latency issues. Drop the lock, wait a while and retry */ /* Latency issues. Drop the lock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
goto retry; goto retry;
...@@ -1235,7 +1235,7 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1235,7 +1235,7 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip,
someone changes the status */ someone changes the status */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + HZ; timeo = jiffies + HZ;
...@@ -1247,9 +1247,9 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1247,9 +1247,9 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip,
map_write(map, CMD(0xD0), adr); map_write(map, CMD(0xD0), adr);
chip->state = FL_UNLOCKING; chip->state = FL_UNLOCKING;
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
msleep(1000); msleep(1000);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* FIXME. Use a timer to check this, and return immediately. */ /* FIXME. Use a timer to check this, and return immediately. */
/* Once the state machine's known to be working I'll do that */ /* Once the state machine's known to be working I'll do that */
...@@ -1267,21 +1267,21 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, ...@@ -1267,21 +1267,21 @@ static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip,
chip->state = FL_STATUS; chip->state = FL_STATUS;
printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]); printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
DISABLE_VPP(map); DISABLE_VPP(map);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return -EIO; return -EIO;
} }
/* Latency issues. Drop the unlock, wait a while and retry */ /* Latency issues. Drop the unlock, wait a while and retry */
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
cfi_udelay(1); cfi_udelay(1);
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
} }
/* Done and happy. */ /* Done and happy. */
chip->state = FL_STATUS; chip->state = FL_STATUS;
DISABLE_VPP(map); DISABLE_VPP(map);
wake_up(&chip->wq); wake_up(&chip->wq);
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
return 0; return 0;
} }
static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
...@@ -1334,7 +1334,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd) ...@@ -1334,7 +1334,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd)
for (i=0; !ret && i<cfi->numchips; i++) { for (i=0; !ret && i<cfi->numchips; i++) {
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
switch(chip->state) { switch(chip->state) {
case FL_READY: case FL_READY:
...@@ -1354,7 +1354,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd) ...@@ -1354,7 +1354,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd)
ret = -EAGAIN; ret = -EAGAIN;
break; break;
} }
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
} }
/* Unlock the chips again */ /* Unlock the chips again */
...@@ -1363,7 +1363,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd) ...@@ -1363,7 +1363,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd)
for (i--; i >=0; i--) { for (i--; i >=0; i--) {
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
if (chip->state == FL_PM_SUSPENDED) { if (chip->state == FL_PM_SUSPENDED) {
/* No need to force it into a known state here, /* No need to force it into a known state here,
...@@ -1372,7 +1372,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd) ...@@ -1372,7 +1372,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd)
chip->state = chip->oldstate; chip->state = chip->oldstate;
wake_up(&chip->wq); wake_up(&chip->wq);
} }
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
} }
} }
...@@ -1390,7 +1390,7 @@ static void cfi_staa_resume(struct mtd_info *mtd) ...@@ -1390,7 +1390,7 @@ static void cfi_staa_resume(struct mtd_info *mtd)
chip = &cfi->chips[i]; chip = &cfi->chips[i];
spin_lock_bh(chip->mutex); mutex_lock(&chip->mutex);
/* Go to known state. Chip may have been power cycled */ /* Go to known state. Chip may have been power cycled */
if (chip->state == FL_PM_SUSPENDED) { if (chip->state == FL_PM_SUSPENDED) {
...@@ -1399,7 +1399,7 @@ static void cfi_staa_resume(struct mtd_info *mtd) ...@@ -1399,7 +1399,7 @@ static void cfi_staa_resume(struct mtd_info *mtd)
wake_up(&chip->wq); wake_up(&chip->wq);
} }
spin_unlock_bh(chip->mutex); mutex_unlock(&chip->mutex);
} }
} }
......
...@@ -158,6 +158,7 @@ static int __xipram cfi_chip_setup(struct map_info *map, ...@@ -158,6 +158,7 @@ static int __xipram cfi_chip_setup(struct map_info *map,
__u32 base = 0; __u32 base = 0;
int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor); int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
int i; int i;
int addr_unlock1 = 0x555, addr_unlock2 = 0x2AA;
xip_enable(base, map, cfi); xip_enable(base, map, cfi);
#ifdef DEBUG_CFI #ifdef DEBUG_CFI
...@@ -181,29 +182,6 @@ static int __xipram cfi_chip_setup(struct map_info *map, ...@@ -181,29 +182,6 @@ static int __xipram cfi_chip_setup(struct map_info *map,
for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor); ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
/* Note we put the device back into Read Mode BEFORE going into Auto
* Select Mode, as some devices support nesting of modes, others
* don't. This way should always work.
* On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and
* so should be treated as nops or illegal (and so put the device
* back into Read Mode, which is a nop in this case).
*/
cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
cfi->mfr = cfi_read_query16(map, base);
cfi->id = cfi_read_query16(map, base + ofs_factor);
/* Get AMD/Spansion extended JEDEC ID */
if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
cfi_read_query(map, base + 0xf * ofs_factor);
/* Put it back into Read Mode */
cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
/* Do any necessary byteswapping */ /* Do any necessary byteswapping */
cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID); cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
...@@ -228,6 +206,35 @@ static int __xipram cfi_chip_setup(struct map_info *map, ...@@ -228,6 +206,35 @@ static int __xipram cfi_chip_setup(struct map_info *map,
#endif #endif
} }
if (cfi->cfiq->P_ID == P_ID_SST_OLD) {
addr_unlock1 = 0x5555;
addr_unlock2 = 0x2AAA;
}
/*
* Note we put the device back into Read Mode BEFORE going into Auto
* Select Mode, as some devices support nesting of modes, others
* don't. This way should always work.
* On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and
* so should be treated as nops or illegal (and so put the device
* back into Read Mode, which is a nop in this case).
*/
cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0xaa, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, addr_unlock2, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x90, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
cfi->mfr = cfi_read_query16(map, base);
cfi->id = cfi_read_query16(map, base + ofs_factor);
/* Get AMD/Spansion extended JEDEC ID */
if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
cfi_read_query(map, base + 0xf * ofs_factor);
/* Put it back into Read Mode */
cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
map->name, cfi->interleave, cfi->device_type*8, base, map->name, cfi->interleave, cfi->device_type*8, base,
map->bankwidth*8); map->bankwidth*8);
...@@ -269,6 +276,9 @@ static char *vendorname(__u16 vendor) ...@@ -269,6 +276,9 @@ static char *vendorname(__u16 vendor)
case P_ID_SST_PAGE: case P_ID_SST_PAGE:
return "SST Page Write"; return "SST Page Write";
case P_ID_SST_OLD:
return "SST 39VF160x/39VF320x";
case P_ID_INTEL_PERFORMANCE: case P_ID_INTEL_PERFORMANCE:
return "Intel Performance Code"; return "Intel Performance Code";
......
...@@ -104,10 +104,11 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n ...@@ -104,10 +104,11 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
int i; int i;
struct cfi_extquery *extp = NULL; struct cfi_extquery *extp = NULL;
printk(" %s Extended Query Table at 0x%4.4X\n", name, adr);
if (!adr) if (!adr)
goto out; goto out;
printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr);
extp = kmalloc(size, GFP_KERNEL); extp = kmalloc(size, GFP_KERNEL);
if (!extp) { if (!extp) {
printk(KERN_ERR "Failed to allocate memory\n"); printk(KERN_ERR "Failed to allocate memory\n");
......
...@@ -58,10 +58,10 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, ...@@ -58,10 +58,10 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
* to flash memory - that means that we don't have to check status * to flash memory - that means that we don't have to check status
* and timeout. * and timeout.
*/ */
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, adr, FL_LOCKING); ret = get_chip(map, chip, adr, FL_LOCKING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -72,7 +72,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, ...@@ -72,7 +72,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
/* Done and happy. */ /* Done and happy. */
chip->state = chip->oldstate; chip->state = chip->oldstate;
put_chip(map, chip, adr); put_chip(map, chip, adr);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return 0; return 0;
} }
......
...@@ -155,8 +155,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi ...@@ -155,8 +155,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
pchip->start = (i << cfi.chipshift); pchip->start = (i << cfi.chipshift);
pchip->state = FL_READY; pchip->state = FL_READY;
init_waitqueue_head(&pchip->wq); init_waitqueue_head(&pchip->wq);
spin_lock_init(&pchip->_spinlock); mutex_init(&pchip->mutex);
pchip->mutex = &pchip->_spinlock;
} }
} }
...@@ -242,17 +241,19 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) ...@@ -242,17 +241,19 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
/* We need these for the !CONFIG_MODULES case, /* We need these for the !CONFIG_MODULES case,
because symbol_get() doesn't work there */ because symbol_get() doesn't work there */
#ifdef CONFIG_MTD_CFI_INTELEXT #ifdef CONFIG_MTD_CFI_INTELEXT
case 0x0001: case P_ID_INTEL_EXT:
case 0x0003: case P_ID_INTEL_STD:
case 0x0200: case P_ID_INTEL_PERFORMANCE:
return cfi_cmdset_0001(map, primary); return cfi_cmdset_0001(map, primary);
#endif #endif
#ifdef CONFIG_MTD_CFI_AMDSTD #ifdef CONFIG_MTD_CFI_AMDSTD
case 0x0002: case P_ID_AMD_STD:
case P_ID_SST_OLD:
case P_ID_WINBOND:
return cfi_cmdset_0002(map, primary); return cfi_cmdset_0002(map, primary);
#endif #endif
#ifdef CONFIG_MTD_CFI_STAA #ifdef CONFIG_MTD_CFI_STAA
case 0x0020: case P_ID_ST_ADV:
return cfi_cmdset_0020(map, primary); return cfi_cmdset_0020(map, primary);
#endif #endif
default: default:
......
此差异已折叠。
# #
# linux/drivers/devices/Makefile # linux/drivers/mtd/devices/Makefile
# #
obj-$(CONFIG_MTD_DOC2000) += doc2000.o obj-$(CONFIG_MTD_DOC2000) += doc2000.o
......
...@@ -276,12 +276,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) ...@@ -276,12 +276,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
/* Setup the MTD structure */ /* Setup the MTD structure */
/* make the name contain the block device in */ /* make the name contain the block device in */
name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1, name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
GFP_KERNEL);
if (!name) if (!name)
goto devinit_err; goto devinit_err;
sprintf(name, "block2mtd: %s", devname);
dev->mtd.name = name; dev->mtd.name = name;
dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
......
...@@ -668,7 +668,7 @@ static int __init init_pmc551(void) ...@@ -668,7 +668,7 @@ static int __init init_pmc551(void)
{ {
struct pci_dev *PCI_Device = NULL; struct pci_dev *PCI_Device = NULL;
struct mypriv *priv; struct mypriv *priv;
int count, found = 0; int found = 0;
struct mtd_info *mtd; struct mtd_info *mtd;
u32 length = 0; u32 length = 0;
...@@ -695,7 +695,7 @@ static int __init init_pmc551(void) ...@@ -695,7 +695,7 @@ static int __init init_pmc551(void)
/* /*
* PCU-bus chipset probe. * PCU-bus chipset probe.
*/ */
for (count = 0; count < MAX_MTD_DEVICES; count++) { for (;;) {
if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI, if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
PCI_DEVICE_ID_V3_SEMI_V370PDC, PCI_DEVICE_ID_V3_SEMI_V370PDC,
......
...@@ -73,15 +73,25 @@ static struct flash_info __initdata sst25l_flash_info[] = { ...@@ -73,15 +73,25 @@ static struct flash_info __initdata sst25l_flash_info[] = {
static int sst25l_status(struct sst25l_flash *flash, int *status) static int sst25l_status(struct sst25l_flash *flash, int *status)
{ {
unsigned char command, response; struct spi_message m;
struct spi_transfer t;
unsigned char cmd_resp[2];
int err; int err;
command = SST25L_CMD_RDSR; spi_message_init(&m);
err = spi_write_then_read(flash->spi, &command, 1, &response, 1); memset(&t, 0, sizeof(struct spi_transfer));
cmd_resp[0] = SST25L_CMD_RDSR;
cmd_resp[1] = 0xff;
t.tx_buf = cmd_resp;
t.rx_buf = cmd_resp;
t.len = sizeof(cmd_resp);
spi_message_add_tail(&t, &m);
err = spi_sync(flash->spi, &m);
if (err < 0) if (err < 0)
return err; return err;
*status = response; *status = cmd_resp[1];
return 0; return 0;
} }
...@@ -328,33 +338,32 @@ static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -328,33 +338,32 @@ static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len,
static struct flash_info *__init sst25l_match_device(struct spi_device *spi) static struct flash_info *__init sst25l_match_device(struct spi_device *spi)
{ {
struct flash_info *flash_info = NULL; struct flash_info *flash_info = NULL;
unsigned char command[4], response; struct spi_message m;
struct spi_transfer t;
unsigned char cmd_resp[6];
int i, err; int i, err;
uint16_t id; uint16_t id;
command[0] = SST25L_CMD_READ_ID; spi_message_init(&m);
command[1] = 0; memset(&t, 0, sizeof(struct spi_transfer));
command[2] = 0;
command[3] = 0; cmd_resp[0] = SST25L_CMD_READ_ID;
err = spi_write_then_read(spi, command, sizeof(command), &response, 1); cmd_resp[1] = 0;
cmd_resp[2] = 0;
cmd_resp[3] = 0;
cmd_resp[4] = 0xff;
cmd_resp[5] = 0xff;
t.tx_buf = cmd_resp;
t.rx_buf = cmd_resp;
t.len = sizeof(cmd_resp);
spi_message_add_tail(&t, &m);
err = spi_sync(spi, &m);
if (err < 0) { if (err < 0) {
dev_err(&spi->dev, "error reading device id msb\n"); dev_err(&spi->dev, "error reading device id\n");
return NULL; return NULL;
} }
id = response << 8; id = (cmd_resp[4] << 8) | cmd_resp[5];
command[0] = SST25L_CMD_READ_ID;
command[1] = 0;
command[2] = 0;
command[3] = 1;
err = spi_write_then_read(spi, command, sizeof(command), &response, 1);
if (err < 0) {
dev_err(&spi->dev, "error reading device id lsb\n");
return NULL;
}
id |= response;
for (i = 0; i < ARRAY_SIZE(sst25l_flash_info); i++) for (i = 0; i < ARRAY_SIZE(sst25l_flash_info); i++)
if (sst25l_flash_info[i].device_id == id) if (sst25l_flash_info[i].device_id == id)
...@@ -411,17 +420,6 @@ static int __init sst25l_probe(struct spi_device *spi) ...@@ -411,17 +420,6 @@ static int __init sst25l_probe(struct spi_device *spi)
flash->mtd.erasesize, flash->mtd.erasesize / 1024, flash->mtd.erasesize, flash->mtd.erasesize / 1024,
flash->mtd.numeraseregions); flash->mtd.numeraseregions);
if (flash->mtd.numeraseregions)
for (i = 0; i < flash->mtd.numeraseregions; i++)
DEBUG(MTD_DEBUG_LEVEL2,
"mtd.eraseregions[%d] = { .offset = 0x%llx, "
".erasesize = 0x%.8x (%uKiB), "
".numblocks = %d }\n",
i, (long long)flash->mtd.eraseregions[i].offset,
flash->mtd.eraseregions[i].erasesize,
flash->mtd.eraseregions[i].erasesize / 1024,
flash->mtd.eraseregions[i].numblocks);
if (mtd_has_partitions()) { if (mtd_has_partitions()) {
struct mtd_partition *parts = NULL; struct mtd_partition *parts = NULL;
int nr_parts = 0; int nr_parts = 0;
......
...@@ -1082,7 +1082,6 @@ static void ftl_remove_dev(struct mtd_blktrans_dev *dev) ...@@ -1082,7 +1082,6 @@ static void ftl_remove_dev(struct mtd_blktrans_dev *dev)
{ {
del_mtd_blktrans_dev(dev); del_mtd_blktrans_dev(dev);
ftl_freepart((partition_t *)dev); ftl_freepart((partition_t *)dev);
kfree(dev);
} }
static struct mtd_blktrans_ops ftl_tr = { static struct mtd_blktrans_ops ftl_tr = {
......
...@@ -139,7 +139,6 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev) ...@@ -139,7 +139,6 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
kfree(inftl->PUtable); kfree(inftl->PUtable);
kfree(inftl->VUtable); kfree(inftl->VUtable);
kfree(inftl);
} }
/* /*
......
...@@ -100,9 +100,10 @@ static int find_boot_record(struct INFTLrecord *inftl) ...@@ -100,9 +100,10 @@ static int find_boot_record(struct INFTLrecord *inftl)
} }
/* To be safer with BIOS, also use erase mark as discriminant */ /* To be safer with BIOS, also use erase mark as discriminant */
if ((ret = inftl_read_oob(mtd, block * inftl->EraseSize + ret = inftl_read_oob(mtd,
SECTORSIZE + 8, 8, &retlen, block * inftl->EraseSize + SECTORSIZE + 8,
(char *)&h1) < 0)) { 8, &retlen,(char *)&h1);
if (ret < 0) {
printk(KERN_WARNING "INFTL: ANAND header found at " printk(KERN_WARNING "INFTL: ANAND header found at "
"0x%x in mtd%d, but OOB data read failed " "0x%x in mtd%d, but OOB data read failed "
"(err %d)\n", block * inftl->EraseSize, "(err %d)\n", block * inftl->EraseSize,
......
...@@ -107,8 +107,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map) ...@@ -107,8 +107,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
/* those should be reset too since /* those should be reset too since
they create memory references. */ they create memory references. */
init_waitqueue_head(&chip->wq); init_waitqueue_head(&chip->wq);
spin_lock_init(&chip->_spinlock); mutex_init(&chip->mutex);
chip->mutex = &chip->_spinlock;
chip++; chip++;
} }
} }
...@@ -144,7 +143,7 @@ static int wait_for_ready(struct map_info *map, struct flchip *chip, ...@@ -144,7 +143,7 @@ static int wait_for_ready(struct map_info *map, struct flchip *chip,
} }
/* OK Still waiting. Drop the lock, wait a while and retry. */ /* OK Still waiting. Drop the lock, wait a while and retry. */
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
if (sleep_time >= 1000000/HZ) { if (sleep_time >= 1000000/HZ) {
/* /*
* Half of the normal delay still remaining * Half of the normal delay still remaining
...@@ -159,17 +158,17 @@ static int wait_for_ready(struct map_info *map, struct flchip *chip, ...@@ -159,17 +158,17 @@ static int wait_for_ready(struct map_info *map, struct flchip *chip,
cond_resched(); cond_resched();
timeo--; timeo--;
} }
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
while (chip->state != chip_state) { while (chip->state != chip_state) {
/* Someone's suspended the operation: sleep */ /* Someone's suspended the operation: sleep */
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
} }
if (chip->erase_suspended || chip->write_suspended) { if (chip->erase_suspended || chip->write_suspended) {
/* Suspend has occured while sleep: reset timeout */ /* Suspend has occured while sleep: reset timeout */
...@@ -230,20 +229,20 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) ...@@ -230,20 +229,20 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
* it'll happily send us to sleep. In any case, when * it'll happily send us to sleep. In any case, when
* get_chip returns success we're clear to go ahead. * get_chip returns success we're clear to go ahead.
*/ */
ret = spin_trylock(contender->mutex); ret = mutex_trylock(&contender->mutex);
spin_unlock(&shared->lock); spin_unlock(&shared->lock);
if (!ret) if (!ret)
goto retry; goto retry;
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
ret = chip_ready(map, contender, mode); ret = chip_ready(map, contender, mode);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
goto retry; goto retry;
} }
if (ret) { if (ret) {
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
return ret; return ret;
} }
spin_lock(&shared->lock); spin_lock(&shared->lock);
...@@ -252,10 +251,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) ...@@ -252,10 +251,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
* state. Put contender and retry. */ * state. Put contender and retry. */
if (chip->state == FL_SYNCING) { if (chip->state == FL_SYNCING) {
put_chip(map, contender); put_chip(map, contender);
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
goto retry; goto retry;
} }
spin_unlock(contender->mutex); mutex_unlock(&contender->mutex);
} }
/* Check if we have suspended erase on this chip. /* Check if we have suspended erase on this chip.
...@@ -265,10 +264,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) ...@@ -265,10 +264,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
spin_unlock(&shared->lock); spin_unlock(&shared->lock);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
goto retry; goto retry;
} }
...@@ -337,10 +336,10 @@ static int chip_ready(struct map_info *map, struct flchip *chip, int mode) ...@@ -337,10 +336,10 @@ static int chip_ready(struct map_info *map, struct flchip *chip, int mode)
sleep: sleep:
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait); add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
schedule(); schedule();
remove_wait_queue(&chip->wq, &wait); remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
return -EAGAIN; return -EAGAIN;
} }
} }
...@@ -356,12 +355,12 @@ static void put_chip(struct map_info *map, struct flchip *chip) ...@@ -356,12 +355,12 @@ static void put_chip(struct map_info *map, struct flchip *chip)
if (shared->writing && shared->writing != chip) { if (shared->writing && shared->writing != chip) {
/* give back the ownership */ /* give back the ownership */
struct flchip *loaner = shared->writing; struct flchip *loaner = shared->writing;
spin_lock(loaner->mutex); mutex_lock(&loaner->mutex);
spin_unlock(&shared->lock); spin_unlock(&shared->lock);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
put_chip(map, loaner); put_chip(map, loaner);
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
spin_unlock(loaner->mutex); mutex_unlock(&loaner->mutex);
wake_up(&chip->wq); wake_up(&chip->wq);
return; return;
} }
...@@ -414,10 +413,10 @@ int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -414,10 +413,10 @@ int do_write_buffer(struct map_info *map, struct flchip *chip,
wbufsize = 1 << lpddr->qinfo->BufSizeShift; wbufsize = 1 << lpddr->qinfo->BufSizeShift;
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, FL_WRITING); ret = get_chip(map, chip, FL_WRITING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
/* Figure out the number of words to write */ /* Figure out the number of words to write */
...@@ -478,7 +477,7 @@ int do_write_buffer(struct map_info *map, struct flchip *chip, ...@@ -478,7 +477,7 @@ int do_write_buffer(struct map_info *map, struct flchip *chip,
} }
out: put_chip(map, chip); out: put_chip(map, chip);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -490,10 +489,10 @@ int do_erase_oneblock(struct mtd_info *mtd, loff_t adr) ...@@ -490,10 +489,10 @@ int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
struct flchip *chip = &lpddr->chips[chipnum]; struct flchip *chip = &lpddr->chips[chipnum];
int ret; int ret;
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, FL_ERASING); ret = get_chip(map, chip, FL_ERASING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
send_pfow_command(map, LPDDR_BLOCK_ERASE, adr, 0, NULL); send_pfow_command(map, LPDDR_BLOCK_ERASE, adr, 0, NULL);
...@@ -505,7 +504,7 @@ int do_erase_oneblock(struct mtd_info *mtd, loff_t adr) ...@@ -505,7 +504,7 @@ int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
goto out; goto out;
} }
out: put_chip(map, chip); out: put_chip(map, chip);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -518,10 +517,10 @@ static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len, ...@@ -518,10 +517,10 @@ static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
struct flchip *chip = &lpddr->chips[chipnum]; struct flchip *chip = &lpddr->chips[chipnum];
int ret = 0; int ret = 0;
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, FL_READY); ret = get_chip(map, chip, FL_READY);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -529,7 +528,7 @@ static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len, ...@@ -529,7 +528,7 @@ static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
*retlen = len; *retlen = len;
put_chip(map, chip); put_chip(map, chip);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -569,9 +568,9 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len, ...@@ -569,9 +568,9 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
else else
thislen = len; thislen = len;
/* get the chip */ /* get the chip */
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, FL_POINT); ret = get_chip(map, chip, FL_POINT);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
if (ret) if (ret)
break; break;
...@@ -611,7 +610,7 @@ static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len) ...@@ -611,7 +610,7 @@ static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
else else
thislen = len; thislen = len;
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
if (chip->state == FL_POINT) { if (chip->state == FL_POINT) {
chip->ref_point_counter--; chip->ref_point_counter--;
if (chip->ref_point_counter == 0) if (chip->ref_point_counter == 0)
...@@ -621,7 +620,7 @@ static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len) ...@@ -621,7 +620,7 @@ static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
"pointed region\n", map->name); "pointed region\n", map->name);
put_chip(map, chip); put_chip(map, chip);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
len -= thislen; len -= thislen;
ofs = 0; ofs = 0;
...@@ -727,10 +726,10 @@ int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk) ...@@ -727,10 +726,10 @@ int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
int chipnum = adr >> lpddr->chipshift; int chipnum = adr >> lpddr->chipshift;
struct flchip *chip = &lpddr->chips[chipnum]; struct flchip *chip = &lpddr->chips[chipnum];
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, FL_LOCKING); ret = get_chip(map, chip, FL_LOCKING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -750,7 +749,7 @@ int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk) ...@@ -750,7 +749,7 @@ int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
goto out; goto out;
} }
out: put_chip(map, chip); out: put_chip(map, chip);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -771,10 +770,10 @@ int word_program(struct map_info *map, loff_t adr, uint32_t curval) ...@@ -771,10 +770,10 @@ int word_program(struct map_info *map, loff_t adr, uint32_t curval)
int chipnum = adr >> lpddr->chipshift; int chipnum = adr >> lpddr->chipshift;
struct flchip *chip = &lpddr->chips[chipnum]; struct flchip *chip = &lpddr->chips[chipnum];
spin_lock(chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, FL_WRITING); ret = get_chip(map, chip, FL_WRITING);
if (ret) { if (ret) {
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
...@@ -788,7 +787,7 @@ int word_program(struct map_info *map, loff_t adr, uint32_t curval) ...@@ -788,7 +787,7 @@ int word_program(struct map_info *map, loff_t adr, uint32_t curval)
} }
out: put_chip(map, chip); out: put_chip(map, chip);
spin_unlock(chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
} }
......
...@@ -134,13 +134,12 @@ static int lpddr_pfow_present(struct map_info *map, struct lpddr_private *lpddr) ...@@ -134,13 +134,12 @@ static int lpddr_pfow_present(struct map_info *map, struct lpddr_private *lpddr)
static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr) static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr)
{ {
lpddr->qinfo = kmalloc(sizeof(struct qinfo_chip), GFP_KERNEL); lpddr->qinfo = kzalloc(sizeof(struct qinfo_chip), GFP_KERNEL);
if (!lpddr->qinfo) { if (!lpddr->qinfo) {
printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n", printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n",
map->name); map->name);
return 0; return 0;
} }
memset(lpddr->qinfo, 0, sizeof(struct qinfo_chip));
/* Get the ManuID */ /* Get the ManuID */
lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID)); lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID));
...@@ -185,13 +184,11 @@ static struct lpddr_private *lpddr_probe_chip(struct map_info *map) ...@@ -185,13 +184,11 @@ static struct lpddr_private *lpddr_probe_chip(struct map_info *map)
lpddr.numchips = 1; lpddr.numchips = 1;
numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum; numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum;
retlpddr = kmalloc(sizeof(struct lpddr_private) + retlpddr = kzalloc(sizeof(struct lpddr_private) +
numvirtchips * sizeof(struct flchip), GFP_KERNEL); numvirtchips * sizeof(struct flchip), GFP_KERNEL);
if (!retlpddr) if (!retlpddr)
return NULL; return NULL;
memset(retlpddr, 0, sizeof(struct lpddr_private) +
numvirtchips * sizeof(struct flchip));
memcpy(retlpddr, &lpddr, sizeof(struct lpddr_private)); memcpy(retlpddr, &lpddr, sizeof(struct lpddr_private));
retlpddr->numchips = numvirtchips; retlpddr->numchips = numvirtchips;
......
...@@ -435,7 +435,7 @@ config MTD_PCI ...@@ -435,7 +435,7 @@ config MTD_PCI
config MTD_PCMCIA config MTD_PCMCIA
tristate "PCMCIA MTD driver" tristate "PCMCIA MTD driver"
depends on PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN depends on PCMCIA && MTD_COMPLEX_MAPPINGS
help help
Map driver for accessing PCMCIA linear flash memory cards. These Map driver for accessing PCMCIA linear flash memory cards. These
cards are usually around 4-16MiB in size. This does not include cards are usually around 4-16MiB in size. This does not include
......
...@@ -70,7 +70,7 @@ static void switch_back(struct async_state *state) ...@@ -70,7 +70,7 @@ static void switch_back(struct async_state *state)
local_irq_restore(state->irq_flags); local_irq_restore(state->irq_flags);
} }
static map_word bfin_read(struct map_info *map, unsigned long ofs) static map_word bfin_flash_read(struct map_info *map, unsigned long ofs)
{ {
struct async_state *state = (struct async_state *)map->map_priv_1; struct async_state *state = (struct async_state *)map->map_priv_1;
uint16_t word; uint16_t word;
...@@ -86,7 +86,7 @@ static map_word bfin_read(struct map_info *map, unsigned long ofs) ...@@ -86,7 +86,7 @@ static map_word bfin_read(struct map_info *map, unsigned long ofs)
return test; return test;
} }
static void bfin_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) static void bfin_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{ {
struct async_state *state = (struct async_state *)map->map_priv_1; struct async_state *state = (struct async_state *)map->map_priv_1;
...@@ -97,7 +97,7 @@ static void bfin_copy_from(struct map_info *map, void *to, unsigned long from, s ...@@ -97,7 +97,7 @@ static void bfin_copy_from(struct map_info *map, void *to, unsigned long from, s
switch_back(state); switch_back(state);
} }
static void bfin_write(struct map_info *map, map_word d1, unsigned long ofs) static void bfin_flash_write(struct map_info *map, map_word d1, unsigned long ofs)
{ {
struct async_state *state = (struct async_state *)map->map_priv_1; struct async_state *state = (struct async_state *)map->map_priv_1;
uint16_t d; uint16_t d;
...@@ -112,7 +112,7 @@ static void bfin_write(struct map_info *map, map_word d1, unsigned long ofs) ...@@ -112,7 +112,7 @@ static void bfin_write(struct map_info *map, map_word d1, unsigned long ofs)
switch_back(state); switch_back(state);
} }
static void bfin_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{ {
struct async_state *state = (struct async_state *)map->map_priv_1; struct async_state *state = (struct async_state *)map->map_priv_1;
...@@ -141,10 +141,10 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) ...@@ -141,10 +141,10 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
state->map.name = DRIVER_NAME; state->map.name = DRIVER_NAME;
state->map.read = bfin_read; state->map.read = bfin_flash_read;
state->map.copy_from = bfin_copy_from; state->map.copy_from = bfin_flash_copy_from;
state->map.write = bfin_write; state->map.write = bfin_flash_write;
state->map.copy_to = bfin_copy_to; state->map.copy_to = bfin_flash_copy_to;
state->map.bankwidth = pdata->width; state->map.bankwidth = pdata->width;
state->map.size = memory->end - memory->start + 1; state->map.size = memory->end - memory->start + 1;
state->map.virt = (void __iomem *)memory->start; state->map.virt = (void __iomem *)memory->start;
......
...@@ -253,7 +253,7 @@ static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd ...@@ -253,7 +253,7 @@ static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd
static int __init clps_setup_flash(void) static int __init clps_setup_flash(void)
{ {
int nr; int nr = 0;
#ifdef CONFIG_ARCH_CEIVA #ifdef CONFIG_ARCH_CEIVA
if (machine_is_ceiva()) { if (machine_is_ceiva()) {
......
...@@ -165,12 +165,11 @@ static int ixp2000_flash_probe(struct platform_device *dev) ...@@ -165,12 +165,11 @@ static int ixp2000_flash_probe(struct platform_device *dev)
return -EIO; return -EIO;
} }
info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL); info = kzalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
if(!info) { if(!info) {
err = -ENOMEM; err = -ENOMEM;
goto Error; goto Error;
} }
memset(info, 0, sizeof(struct ixp2000_flash_info));
platform_set_drvdata(dev, info); platform_set_drvdata(dev, info);
......
...@@ -107,8 +107,8 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, ...@@ -107,8 +107,8 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
return; return;
if (from & 1) { if (from & 1) {
*dest++ = BYTE1(flash_read16(src)); *dest++ = BYTE1(flash_read16(src-1));
src++; src++;
--len; --len;
} }
...@@ -196,12 +196,11 @@ static int ixp4xx_flash_probe(struct platform_device *dev) ...@@ -196,12 +196,11 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
return err; return err;
} }
info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL); info = kzalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
if(!info) { if(!info) {
err = -ENOMEM; err = -ENOMEM;
goto Error; goto Error;
} }
memset(info, 0, sizeof(struct ixp4xx_flash_info));
platform_set_drvdata(dev, info); platform_set_drvdata(dev, info);
......
...@@ -40,10 +40,7 @@ MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy"); ...@@ -40,10 +40,7 @@ MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
static const int debug = 0; static const int debug = 0;
#endif #endif
#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg)
#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg) #define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg)
#define DRIVER_DESC "PCMCIA Flash memory card driver" #define DRIVER_DESC "PCMCIA Flash memory card driver"
...@@ -99,7 +96,9 @@ module_param(mem_type, int, 0); ...@@ -99,7 +96,9 @@ module_param(mem_type, int, 0);
MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)"); MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");
/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */ /* read/write{8,16} copy_{from,to} routines with window remapping
* to access whole card
*/
static caddr_t remap_window(struct map_info *map, unsigned long to) static caddr_t remap_window(struct map_info *map, unsigned long to)
{ {
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
...@@ -136,7 +135,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs) ...@@ -136,7 +135,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
return d; return d;
d.x[0] = readb(addr); d.x[0] = readb(addr);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d.x[0]); DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, addr, d.x[0]);
return d; return d;
} }
...@@ -151,7 +150,7 @@ static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs) ...@@ -151,7 +150,7 @@ static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
return d; return d;
d.x[0] = readw(addr); d.x[0] = readw(addr);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d.x[0]); DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, addr, d.x[0]);
return d; return d;
} }
...@@ -161,7 +160,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long ...@@ -161,7 +160,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
unsigned long win_size = dev->win_size; unsigned long win_size = dev->win_size;
DEBUG(3, "to = %p from = %lu len = %u", to, from, len); DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
while(len) { while(len) {
int toread = win_size - (from & (win_size-1)); int toread = win_size - (from & (win_size-1));
caddr_t addr; caddr_t addr;
...@@ -189,7 +188,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long ...@@ -189,7 +188,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long
if(!addr) if(!addr)
return; return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, addr, d.x[0]); DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", adr, addr, d.x[0]);
writeb(d.x[0], addr); writeb(d.x[0], addr);
} }
...@@ -200,7 +199,7 @@ static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long ...@@ -200,7 +199,7 @@ static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long
if(!addr) if(!addr)
return; return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, addr, d.x[0]); DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", adr, addr, d.x[0]);
writew(d.x[0], addr); writew(d.x[0], addr);
} }
...@@ -210,7 +209,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v ...@@ -210,7 +209,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
unsigned long win_size = dev->win_size; unsigned long win_size = dev->win_size;
DEBUG(3, "to = %lu from = %p len = %u", to, from, len); DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
while(len) { while(len) {
int towrite = win_size - (to & (win_size-1)); int towrite = win_size - (to & (win_size-1));
caddr_t addr; caddr_t addr;
...@@ -244,7 +243,8 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) ...@@ -244,7 +243,8 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
return d; return d;
d.x[0] = readb(win_base + ofs); d.x[0] = readb(win_base + ofs);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d.x[0]); DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx",
ofs, win_base + ofs, d.x[0]);
return d; return d;
} }
...@@ -258,7 +258,8 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs) ...@@ -258,7 +258,8 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
return d; return d;
d.x[0] = readw(win_base + ofs); d.x[0] = readw(win_base + ofs);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d.x[0]); DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx",
ofs, win_base + ofs, d.x[0]);
return d; return d;
} }
...@@ -270,32 +271,34 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ...@@ -270,32 +271,34 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from,
if(DEV_REMOVED(map)) if(DEV_REMOVED(map))
return; return;
DEBUG(3, "to = %p from = %lu len = %u", to, from, len); DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
memcpy_fromio(to, win_base + from, len); memcpy_fromio(to, win_base + from, len);
} }
static void pcmcia_write8(struct map_info *map, u8 d, unsigned long adr) static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr)
{ {
caddr_t win_base = (caddr_t)map->map_priv_2; caddr_t win_base = (caddr_t)map->map_priv_2;
if(DEV_REMOVED(map)) if(DEV_REMOVED(map))
return; return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, win_base + adr, d); DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx",
writeb(d, win_base + adr); adr, win_base + adr, d.x[0]);
writeb(d.x[0], win_base + adr);
} }
static void pcmcia_write16(struct map_info *map, u16 d, unsigned long adr) static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr)
{ {
caddr_t win_base = (caddr_t)map->map_priv_2; caddr_t win_base = (caddr_t)map->map_priv_2;
if(DEV_REMOVED(map)) if(DEV_REMOVED(map))
return; return;
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, win_base + adr, d); DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx",
writew(d, win_base + adr); adr, win_base + adr, d.x[0]);
writew(d.x[0], win_base + adr);
} }
...@@ -306,7 +309,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f ...@@ -306,7 +309,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
if(DEV_REMOVED(map)) if(DEV_REMOVED(map))
return; return;
DEBUG(3, "to = %lu from = %p len = %u", to, from, len); DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
memcpy_toio(win_base + to, from, len); memcpy_toio(win_base + to, from, len);
} }
...@@ -375,7 +378,8 @@ static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev, ...@@ -375,7 +378,8 @@ static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev,
if (!pcmcia_parse_tuple(tuple, &parse)) { if (!pcmcia_parse_tuple(tuple, &parse)) {
cistpl_jedec_t *t = &parse.jedec; cistpl_jedec_t *t = &parse.jedec;
for (i = 0; i < t->nid; i++) for (i = 0; i < t->nid; i++)
DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info); DEBUG(2, "JEDEC: 0x%02x 0x%02x",
t->id[i].mfr, t->id[i].info);
} }
return -ENOSPC; return -ENOSPC;
} }
...@@ -431,7 +435,7 @@ static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev, ...@@ -431,7 +435,7 @@ static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev,
} }
static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev, int *new_name)
{ {
int i; int i;
...@@ -476,7 +480,8 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, ...@@ -476,7 +480,8 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link,
} }
DEBUG(1, "Device: Size: %lu Width:%d Name: %s", DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
dev->pcmcia_map.size, dev->pcmcia_map.bankwidth << 3, dev->mtd_name); dev->pcmcia_map.size,
dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
} }
...@@ -489,7 +494,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -489,7 +494,6 @@ static int pcmciamtd_config(struct pcmcia_device *link)
{ {
struct pcmciamtd_dev *dev = link->priv; struct pcmciamtd_dev *dev = link->priv;
struct mtd_info *mtd = NULL; struct mtd_info *mtd = NULL;
cs_status_t status;
win_req_t req; win_req_t req;
int ret; int ret;
int i; int i;
...@@ -513,9 +517,11 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -513,9 +517,11 @@ static int pcmciamtd_config(struct pcmcia_device *link)
if(setvpp == 1) if(setvpp == 1)
dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp; dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
/* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum /* Request a memory window for PCMCIA. Some architeures can map windows
that PCMCIA can support (64MiB) - this is ideal and we aim for a window the size of the * upto the maximum that PCMCIA can support (64MiB) - this is ideal and
whole card - otherwise we try smaller windows until we succeed */ * we aim for a window the size of the whole card - otherwise we try
* smaller windows until we succeed
*/
req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE; req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE;
req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
...@@ -543,7 +549,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -543,7 +549,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
DEBUG(2, "dev->win_size = %d", dev->win_size); DEBUG(2, "dev->win_size = %d", dev->win_size);
if(!dev->win_size) { if(!dev->win_size) {
err("Cant allocate memory window"); dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
pcmciamtd_release(link); pcmciamtd_release(link);
return -ENODEV; return -ENODEV;
} }
...@@ -553,7 +559,8 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -553,7 +559,8 @@ static int pcmciamtd_config(struct pcmcia_device *link)
DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win); DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win);
dev->win_base = ioremap(req.Base, req.Size); dev->win_base = ioremap(req.Base, req.Size);
if(!dev->win_base) { if(!dev->win_base) {
err("ioremap(%lu, %u) failed", req.Base, req.Size); dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n",
req.Base, req.Size);
pcmciamtd_release(link); pcmciamtd_release(link);
return -ENODEV; return -ENODEV;
} }
...@@ -564,7 +571,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -564,7 +571,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
dev->pcmcia_map.map_priv_1 = (unsigned long)dev; dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
dev->vpp = (vpp) ? vpp : link->socket.socket.Vpp; dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
link->conf.Attributes = 0; link->conf.Attributes = 0;
if(setvpp == 2) { if(setvpp == 2) {
link->conf.Vpp = dev->vpp; link->conf.Vpp = dev->vpp;
...@@ -600,7 +607,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -600,7 +607,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
} }
if(!mtd) { if(!mtd) {
DEBUG(1, "Cant find an MTD"); DEBUG(1, "Can not find an MTD");
pcmciamtd_release(link); pcmciamtd_release(link);
return -ENODEV; return -ENODEV;
} }
...@@ -611,8 +618,9 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -611,8 +618,9 @@ static int pcmciamtd_config(struct pcmcia_device *link)
if(new_name) { if(new_name) {
int size = 0; int size = 0;
char unit = ' '; char unit = ' ';
/* Since we are using a default name, make it better by adding in the /* Since we are using a default name, make it better by adding
size */ * in the size
*/
if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */ if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */
size = mtd->size >> 10; size = mtd->size >> 10;
unit = 'K'; unit = 'K';
...@@ -642,15 +650,15 @@ static int pcmciamtd_config(struct pcmcia_device *link) ...@@ -642,15 +650,15 @@ static int pcmciamtd_config(struct pcmcia_device *link)
if(add_mtd_device(mtd)) { if(add_mtd_device(mtd)) {
map_destroy(mtd); map_destroy(mtd);
dev->mtd_info = NULL; dev->mtd_info = NULL;
err("Couldnt register MTD device"); dev_err(&dev->p_dev->dev,
"Could not register the MTD device\n");
pcmciamtd_release(link); pcmciamtd_release(link);
return -ENODEV; return -ENODEV;
} }
info("mtd%d: %s", mtd->index, mtd->name); dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name);
return 0; return 0;
failed: dev_err(&dev->p_dev->dev, "CS Error, exiting\n");
err("CS Error, exiting");
pcmciamtd_release(link); pcmciamtd_release(link);
return -ENODEV; return -ENODEV;
} }
...@@ -689,8 +697,9 @@ static void pcmciamtd_detach(struct pcmcia_device *link) ...@@ -689,8 +697,9 @@ static void pcmciamtd_detach(struct pcmcia_device *link)
if(dev->mtd_info) { if(dev->mtd_info) {
del_mtd_device(dev->mtd_info); del_mtd_device(dev->mtd_info);
dev_info(&dev->p_dev->dev, "mtd%d: Removing\n",
dev->mtd_info->index);
map_destroy(dev->mtd_info); map_destroy(dev->mtd_info);
info("mtd%d: Removed", dev->mtd_info->index);
} }
pcmciamtd_release(link); pcmciamtd_release(link);
...@@ -734,8 +743,11 @@ static struct pcmcia_device_id pcmciamtd_ids[] = { ...@@ -734,8 +743,11 @@ static struct pcmcia_device_id pcmciamtd_ids[] = {
PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8), PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8),
PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c), PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c),
PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0), PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0),
PCMCIA_DEVICE_PROD_ID123("M-Systems", "M-SYS Flash Memory Card", "(c) M-Systems", 0x7ed2ad87, 0x675dc3fb, 0x7aef3965),
PCMCIA_DEVICE_PROD_ID12("PRETEC", " 2MB SRAM CARD", 0xebf91155, 0x805360ca),
PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b), PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b),
PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad), PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad),
PCMCIA_DEVICE_PROD_ID12("SMART Modular Technologies", " 4MB FLASH Card", 0x96fd8277, 0x737a5b05),
PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca), PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca),
PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944), PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944),
/* the following was commented out in pcmcia-cs-3.2.7 */ /* the following was commented out in pcmcia-cs-3.2.7 */
......
...@@ -264,8 +264,11 @@ static int __init physmap_init(void) ...@@ -264,8 +264,11 @@ static int __init physmap_init(void)
err = platform_driver_register(&physmap_flash_driver); err = platform_driver_register(&physmap_flash_driver);
#ifdef CONFIG_MTD_PHYSMAP_COMPAT #ifdef CONFIG_MTD_PHYSMAP_COMPAT
if (err == 0) if (err == 0) {
platform_device_register(&physmap_flash); err = platform_device_register(&physmap_flash);
if (err)
platform_driver_unregister(&physmap_flash_driver);
}
#endif #endif
return err; return err;
......
...@@ -173,12 +173,53 @@ static struct mtd_info * __devinit obsolete_probe(struct of_device *dev, ...@@ -173,12 +173,53 @@ static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
} }
} }
#ifdef CONFIG_MTD_PARTITIONS
/* When partitions are set we look for a linux,part-probe property which
specifies the list of partition probers to use. If none is given then the
default is use. These take precedence over other device tree
information. */
static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
static const char ** __devinit of_get_probes(struct device_node *dp)
{
const char *cp;
int cplen;
unsigned int l;
unsigned int count;
const char **res;
cp = of_get_property(dp, "linux,part-probe", &cplen);
if (cp == NULL)
return part_probe_types_def;
count = 0;
for (l = 0; l != cplen; l++)
if (cp[l] == 0)
count++;
res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
count = 0;
while (cplen > 0) {
res[count] = cp;
l = strlen(cp) + 1;
cp += l;
cplen -= l;
count++;
}
return res;
}
static void __devinit of_free_probes(const char **probes)
{
if (probes != part_probe_types_def)
kfree(probes);
}
#endif
static int __devinit of_flash_probe(struct of_device *dev, static int __devinit of_flash_probe(struct of_device *dev,
const struct of_device_id *match) const struct of_device_id *match)
{ {
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
static const char *part_probe_types[] const char **part_probe_types;
= { "cmdlinepart", "RedBoot", NULL };
#endif #endif
struct device_node *dp = dev->node; struct device_node *dp = dev->node;
struct resource res; struct resource res;
...@@ -218,7 +259,7 @@ static int __devinit of_flash_probe(struct of_device *dev, ...@@ -218,7 +259,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
dev_set_drvdata(&dev->dev, info); dev_set_drvdata(&dev->dev, info);
mtd_list = kzalloc(sizeof(struct mtd_info) * count, GFP_KERNEL); mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
if (!mtd_list) if (!mtd_list)
goto err_flash_remove; goto err_flash_remove;
...@@ -307,12 +348,14 @@ static int __devinit of_flash_probe(struct of_device *dev, ...@@ -307,12 +348,14 @@ static int __devinit of_flash_probe(struct of_device *dev,
goto err_out; goto err_out;
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
/* First look for RedBoot table or partitions on the command part_probe_types = of_get_probes(dp);
* line, these take precedence over device tree information */
err = parse_mtd_partitions(info->cmtd, part_probe_types, err = parse_mtd_partitions(info->cmtd, part_probe_types,
&info->parts, 0); &info->parts, 0);
if (err < 0) if (err < 0) {
of_free_probes(part_probe_types);
return err; return err;
}
of_free_probes(part_probe_types);
#ifdef CONFIG_MTD_OF_PARTS #ifdef CONFIG_MTD_OF_PARTS
if (err == 0) { if (err == 0) {
......
...@@ -234,6 +234,7 @@ static int __devexit pismo_remove(struct i2c_client *client) ...@@ -234,6 +234,7 @@ static int __devexit pismo_remove(struct i2c_client *client)
/* FIXME: set_vpp needs saner arguments */ /* FIXME: set_vpp needs saner arguments */
pismo_setvpp_remove_fix(pismo); pismo_setvpp_remove_fix(pismo);
i2c_set_clientdata(client, NULL);
kfree(pismo); kfree(pismo);
return 0; return 0;
...@@ -272,7 +273,7 @@ static int __devinit pismo_probe(struct i2c_client *client, ...@@ -272,7 +273,7 @@ static int __devinit pismo_probe(struct i2c_client *client,
ret = pismo_eeprom_read(client, &eeprom, 0, sizeof(eeprom)); ret = pismo_eeprom_read(client, &eeprom, 0, sizeof(eeprom));
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "error reading EEPROM: %d\n", ret); dev_err(&client->dev, "error reading EEPROM: %d\n", ret);
return ret; goto exit_free;
} }
dev_info(&client->dev, "%.15s board found\n", eeprom.board); dev_info(&client->dev, "%.15s board found\n", eeprom.board);
...@@ -283,6 +284,11 @@ static int __devinit pismo_probe(struct i2c_client *client, ...@@ -283,6 +284,11 @@ static int __devinit pismo_probe(struct i2c_client *client,
pdata->cs_addrs[i]); pdata->cs_addrs[i]);
return 0; return 0;
exit_free:
i2c_set_clientdata(client, NULL);
kfree(pismo);
return ret;
} }
static const struct i2c_device_id pismo_id[] = { static const struct i2c_device_id pismo_id[] = {
......
...@@ -63,11 +63,10 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev) ...@@ -63,11 +63,10 @@ static int __init pxa2xx_flash_probe(struct platform_device *pdev)
if (!res) if (!res)
return -ENODEV; return -ENODEV;
info = kmalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL); info = kzalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
memset(info, 0, sizeof(struct pxa2xx_flash_info));
info->map.name = (char *) flash->name; info->map.name = (char *) flash->name;
info->map.bankwidth = flash->width; info->map.bankwidth = flash->width;
info->map.phys = res->start; info->map.phys = res->start;
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/freezer.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -25,12 +24,42 @@ ...@@ -25,12 +24,42 @@
#include "mtdcore.h" #include "mtdcore.h"
static LIST_HEAD(blktrans_majors); static LIST_HEAD(blktrans_majors);
static DEFINE_MUTEX(blktrans_ref_mutex);
void blktrans_dev_release(struct kref *kref)
{
struct mtd_blktrans_dev *dev =
container_of(kref, struct mtd_blktrans_dev, ref);
dev->disk->private_data = NULL;
blk_cleanup_queue(dev->rq);
put_disk(dev->disk);
list_del(&dev->list);
kfree(dev);
}
static struct mtd_blktrans_dev *blktrans_dev_get(struct gendisk *disk)
{
struct mtd_blktrans_dev *dev;
mutex_lock(&blktrans_ref_mutex);
dev = disk->private_data;
if (!dev)
goto unlock;
kref_get(&dev->ref);
unlock:
mutex_unlock(&blktrans_ref_mutex);
return dev;
}
void blktrans_dev_put(struct mtd_blktrans_dev *dev)
{
mutex_lock(&blktrans_ref_mutex);
kref_put(&dev->ref, blktrans_dev_release);
mutex_unlock(&blktrans_ref_mutex);
}
struct mtd_blkcore_priv {
struct task_struct *thread;
struct request_queue *rq;
spinlock_t queue_lock;
};
static int do_blktrans_request(struct mtd_blktrans_ops *tr, static int do_blktrans_request(struct mtd_blktrans_ops *tr,
struct mtd_blktrans_dev *dev, struct mtd_blktrans_dev *dev,
...@@ -61,7 +90,6 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, ...@@ -61,7 +90,6 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
return -EIO; return -EIO;
rq_flush_dcache_pages(req); rq_flush_dcache_pages(req);
return 0; return 0;
case WRITE: case WRITE:
if (!tr->writesect) if (!tr->writesect)
return -EIO; return -EIO;
...@@ -71,7 +99,6 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, ...@@ -71,7 +99,6 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
if (tr->writesect(dev, block, buf)) if (tr->writesect(dev, block, buf))
return -EIO; return -EIO;
return 0; return 0;
default: default:
printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
return -EIO; return -EIO;
...@@ -80,14 +107,13 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, ...@@ -80,14 +107,13 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
static int mtd_blktrans_thread(void *arg) static int mtd_blktrans_thread(void *arg)
{ {
struct mtd_blktrans_ops *tr = arg; struct mtd_blktrans_dev *dev = arg;
struct request_queue *rq = tr->blkcore_priv->rq; struct request_queue *rq = dev->rq;
struct request *req = NULL; struct request *req = NULL;
spin_lock_irq(rq->queue_lock); spin_lock_irq(rq->queue_lock);
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
struct mtd_blktrans_dev *dev;
int res; int res;
if (!req && !(req = blk_fetch_request(rq))) { if (!req && !(req = blk_fetch_request(rq))) {
...@@ -98,13 +124,10 @@ static int mtd_blktrans_thread(void *arg) ...@@ -98,13 +124,10 @@ static int mtd_blktrans_thread(void *arg)
continue; continue;
} }
dev = req->rq_disk->private_data;
tr = dev->tr;
spin_unlock_irq(rq->queue_lock); spin_unlock_irq(rq->queue_lock);
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
res = do_blktrans_request(tr, dev, req); res = do_blktrans_request(dev->tr, dev, req);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
spin_lock_irq(rq->queue_lock); spin_lock_irq(rq->queue_lock);
...@@ -123,81 +146,112 @@ static int mtd_blktrans_thread(void *arg) ...@@ -123,81 +146,112 @@ static int mtd_blktrans_thread(void *arg)
static void mtd_blktrans_request(struct request_queue *rq) static void mtd_blktrans_request(struct request_queue *rq)
{ {
struct mtd_blktrans_ops *tr = rq->queuedata; struct mtd_blktrans_dev *dev;
wake_up_process(tr->blkcore_priv->thread); struct request *req = NULL;
}
dev = rq->queuedata;
if (!dev)
while ((req = blk_fetch_request(rq)) != NULL)
__blk_end_request_all(req, -ENODEV);
else
wake_up_process(dev->thread);
}
static int blktrans_open(struct block_device *bdev, fmode_t mode) static int blktrans_open(struct block_device *bdev, fmode_t mode)
{ {
struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
struct mtd_blktrans_ops *tr = dev->tr; int ret;
int ret = -ENODEV;
if (!dev)
if (!get_mtd_device(NULL, dev->mtd->index)) return -ERESTARTSYS;
goto out;
mutex_lock(&dev->lock);
if (!try_module_get(tr->owner))
goto out_tr; if (!dev->mtd) {
ret = -ENXIO;
/* FIXME: Locking. A hot pluggable device can go away goto unlock;
(del_mtd_device can be called for it) without its module
being unloaded. */
dev->mtd->usecount++;
ret = 0;
if (tr->open && (ret = tr->open(dev))) {
dev->mtd->usecount--;
put_mtd_device(dev->mtd);
out_tr:
module_put(tr->owner);
} }
out:
ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0;
/* Take another reference on the device so it won't go away till
last release */
if (!ret)
kref_get(&dev->ref);
unlock:
mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
return ret; return ret;
} }
static int blktrans_release(struct gendisk *disk, fmode_t mode) static int blktrans_release(struct gendisk *disk, fmode_t mode)
{ {
struct mtd_blktrans_dev *dev = disk->private_data; struct mtd_blktrans_dev *dev = blktrans_dev_get(disk);
struct mtd_blktrans_ops *tr = dev->tr; int ret = -ENXIO;
int ret = 0;
if (tr->release) if (!dev)
ret = tr->release(dev); return ret;
if (!ret) { mutex_lock(&dev->lock);
dev->mtd->usecount--;
put_mtd_device(dev->mtd); /* Release one reference, we sure its not the last one here*/
module_put(tr->owner); kref_put(&dev->ref, blktrans_dev_release);
}
if (!dev->mtd)
goto unlock;
ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0;
unlock:
mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
return ret; return ret;
} }
static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{ {
struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
int ret = -ENXIO;
if (!dev)
return ret;
mutex_lock(&dev->lock);
if (!dev->mtd)
goto unlock;
if (dev->tr->getgeo) ret = dev->tr->getgeo ? dev->tr->getgeo(dev, geo) : 0;
return dev->tr->getgeo(dev, geo); unlock:
return -ENOTTY; mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
return ret;
} }
static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
struct mtd_blktrans_ops *tr = dev->tr; int ret = -ENXIO;
if (!dev)
return ret;
mutex_lock(&dev->lock);
if (!dev->mtd)
goto unlock;
switch (cmd) { switch (cmd) {
case BLKFLSBUF: case BLKFLSBUF:
if (tr->flush) ret = dev->tr->flush ? dev->tr->flush(dev) : 0;
return tr->flush(dev);
/* The core code did the work, we had nothing to do. */
return 0;
default: default:
return -ENOTTY; ret = -ENOTTY;
} }
unlock:
mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
return ret;
} }
static const struct block_device_operations mtd_blktrans_ops = { static const struct block_device_operations mtd_blktrans_ops = {
...@@ -214,12 +268,14 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) ...@@ -214,12 +268,14 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
struct mtd_blktrans_dev *d; struct mtd_blktrans_dev *d;
int last_devnum = -1; int last_devnum = -1;
struct gendisk *gd; struct gendisk *gd;
int ret;
if (mutex_trylock(&mtd_table_mutex)) { if (mutex_trylock(&mtd_table_mutex)) {
mutex_unlock(&mtd_table_mutex); mutex_unlock(&mtd_table_mutex);
BUG(); BUG();
} }
mutex_lock(&blktrans_ref_mutex);
list_for_each_entry(d, &tr->devs, list) { list_for_each_entry(d, &tr->devs, list) {
if (new->devnum == -1) { if (new->devnum == -1) {
/* Use first free number */ /* Use first free number */
...@@ -231,6 +287,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) ...@@ -231,6 +287,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
} }
} else if (d->devnum == new->devnum) { } else if (d->devnum == new->devnum) {
/* Required number taken */ /* Required number taken */
mutex_unlock(&blktrans_ref_mutex);
return -EBUSY; return -EBUSY;
} else if (d->devnum > new->devnum) { } else if (d->devnum > new->devnum) {
/* Required number was free */ /* Required number was free */
...@@ -239,24 +296,38 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) ...@@ -239,24 +296,38 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
} }
last_devnum = d->devnum; last_devnum = d->devnum;
} }
ret = -EBUSY;
if (new->devnum == -1) if (new->devnum == -1)
new->devnum = last_devnum+1; new->devnum = last_devnum+1;
if ((new->devnum << tr->part_bits) > 256) { /* Check that the device and any partitions will get valid
return -EBUSY; * minor numbers and that the disk naming code below can cope
* with this number. */
if (new->devnum > (MINORMASK >> tr->part_bits) ||
(tr->part_bits && new->devnum >= 27 * 26)) {
mutex_unlock(&blktrans_ref_mutex);
goto error1;
} }
list_add_tail(&new->list, &tr->devs); list_add_tail(&new->list, &tr->devs);
added: added:
mutex_unlock(&blktrans_ref_mutex);
mutex_init(&new->lock); mutex_init(&new->lock);
kref_init(&new->ref);
if (!tr->writesect) if (!tr->writesect)
new->readonly = 1; new->readonly = 1;
/* Create gendisk */
ret = -ENOMEM;
gd = alloc_disk(1 << tr->part_bits); gd = alloc_disk(1 << tr->part_bits);
if (!gd) {
list_del(&new->list); if (!gd)
return -ENOMEM; goto error2;
}
new->disk = gd;
gd->private_data = new;
gd->major = tr->major; gd->major = tr->major;
gd->first_minor = (new->devnum) << tr->part_bits; gd->first_minor = (new->devnum) << tr->part_bits;
gd->fops = &mtd_blktrans_ops; gd->fops = &mtd_blktrans_ops;
...@@ -274,13 +345,35 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) ...@@ -274,13 +345,35 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
snprintf(gd->disk_name, sizeof(gd->disk_name), snprintf(gd->disk_name, sizeof(gd->disk_name),
"%s%d", tr->name, new->devnum); "%s%d", tr->name, new->devnum);
/* 2.5 has capacity in units of 512 bytes while still
having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
set_capacity(gd, (new->size * tr->blksize) >> 9); set_capacity(gd, (new->size * tr->blksize) >> 9);
gd->private_data = new; /* Create the request queue */
new->blkcore_priv = gd; spin_lock_init(&new->queue_lock);
gd->queue = tr->blkcore_priv->rq; new->rq = blk_init_queue(mtd_blktrans_request, &new->queue_lock);
if (!new->rq)
goto error3;
new->rq->queuedata = new;
blk_queue_logical_block_size(new->rq, tr->blksize);
if (tr->discard)
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
new->rq);
gd->queue = new->rq;
__get_mtd_device(new->mtd);
__module_get(tr->owner);
/* Create processing thread */
/* TODO: workqueue ? */
new->thread = kthread_run(mtd_blktrans_thread, new,
"%s%d", tr->name, new->mtd->index);
if (IS_ERR(new->thread)) {
ret = PTR_ERR(new->thread);
goto error4;
}
gd->driverfs_dev = &new->mtd->dev; gd->driverfs_dev = &new->mtd->dev;
if (new->readonly) if (new->readonly)
...@@ -288,21 +381,65 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) ...@@ -288,21 +381,65 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
add_disk(gd); add_disk(gd);
if (new->disk_attributes) {
ret = sysfs_create_group(&disk_to_dev(gd)->kobj,
new->disk_attributes);
WARN_ON(ret);
}
return 0; return 0;
error4:
module_put(tr->owner);
__put_mtd_device(new->mtd);
blk_cleanup_queue(new->rq);
error3:
put_disk(new->disk);
error2:
list_del(&new->list);
error1:
kfree(new);
return ret;
} }
int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
{ {
unsigned long flags;
if (mutex_trylock(&mtd_table_mutex)) { if (mutex_trylock(&mtd_table_mutex)) {
mutex_unlock(&mtd_table_mutex); mutex_unlock(&mtd_table_mutex);
BUG(); BUG();
} }
list_del(&old->list); /* Stop new requests to arrive */
del_gendisk(old->disk);
if (old->disk_attributes)
sysfs_remove_group(&disk_to_dev(old->disk)->kobj,
old->disk_attributes);
/* Stop the thread */
kthread_stop(old->thread);
/* Kill current requests */
spin_lock_irqsave(&old->queue_lock, flags);
old->rq->queuedata = NULL;
blk_start_queue(old->rq);
spin_unlock_irqrestore(&old->queue_lock, flags);
/* Ask trans driver for release to the mtd device */
mutex_lock(&old->lock);
if (old->open && old->tr->release) {
old->tr->release(old);
old->open = 0;
}
__put_mtd_device(old->mtd);
module_put(old->tr->owner);
del_gendisk(old->blkcore_priv); /* At that point, we don't touch the mtd anymore */
put_disk(old->blkcore_priv); old->mtd = NULL;
mutex_unlock(&old->lock);
blktrans_dev_put(old);
return 0; return 0;
} }
...@@ -335,7 +472,8 @@ static struct mtd_notifier blktrans_notifier = { ...@@ -335,7 +472,8 @@ static struct mtd_notifier blktrans_notifier = {
int register_mtd_blktrans(struct mtd_blktrans_ops *tr) int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
{ {
int ret, i; struct mtd_info *mtd;
int ret;
/* Register the notifier if/when the first device type is /* Register the notifier if/when the first device type is
registered, to prevent the link/init ordering from fucking registered, to prevent the link/init ordering from fucking
...@@ -343,9 +481,6 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) ...@@ -343,9 +481,6 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
if (!blktrans_notifier.list.next) if (!blktrans_notifier.list.next)
register_mtd_user(&blktrans_notifier); register_mtd_user(&blktrans_notifier);
tr->blkcore_priv = kzalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
if (!tr->blkcore_priv)
return -ENOMEM;
mutex_lock(&mtd_table_mutex); mutex_lock(&mtd_table_mutex);
...@@ -353,49 +488,20 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) ...@@ -353,49 +488,20 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
if (ret) { if (ret) {
printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
tr->name, tr->major, ret); tr->name, tr->major, ret);
kfree(tr->blkcore_priv);
mutex_unlock(&mtd_table_mutex); mutex_unlock(&mtd_table_mutex);
return ret; return ret;
} }
spin_lock_init(&tr->blkcore_priv->queue_lock);
tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock);
if (!tr->blkcore_priv->rq) {
unregister_blkdev(tr->major, tr->name);
kfree(tr->blkcore_priv);
mutex_unlock(&mtd_table_mutex);
return -ENOMEM;
}
tr->blkcore_priv->rq->queuedata = tr;
blk_queue_logical_block_size(tr->blkcore_priv->rq, tr->blksize);
if (tr->discard)
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
tr->blkcore_priv->rq);
tr->blkshift = ffs(tr->blksize) - 1; tr->blkshift = ffs(tr->blksize) - 1;
tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr,
"%sd", tr->name);
if (IS_ERR(tr->blkcore_priv->thread)) {
ret = PTR_ERR(tr->blkcore_priv->thread);
blk_cleanup_queue(tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name);
kfree(tr->blkcore_priv);
mutex_unlock(&mtd_table_mutex);
return ret;
}
INIT_LIST_HEAD(&tr->devs); INIT_LIST_HEAD(&tr->devs);
list_add(&tr->list, &blktrans_majors); list_add(&tr->list, &blktrans_majors);
for (i=0; i<MAX_MTD_DEVICES; i++) { mtd_for_each_device(mtd)
if (mtd_table[i] && mtd_table[i]->type != MTD_ABSENT) if (mtd->type != MTD_ABSENT)
tr->add_mtd(tr, mtd_table[i]); tr->add_mtd(tr, mtd);
}
mutex_unlock(&mtd_table_mutex); mutex_unlock(&mtd_table_mutex);
return 0; return 0;
} }
...@@ -405,22 +511,15 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) ...@@ -405,22 +511,15 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
mutex_lock(&mtd_table_mutex); mutex_lock(&mtd_table_mutex);
/* Clean up the kernel thread */
kthread_stop(tr->blkcore_priv->thread);
/* Remove it from the list of active majors */ /* Remove it from the list of active majors */
list_del(&tr->list); list_del(&tr->list);
list_for_each_entry_safe(dev, next, &tr->devs, list) list_for_each_entry_safe(dev, next, &tr->devs, list)
tr->remove_dev(dev); tr->remove_dev(dev);
blk_cleanup_queue(tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name); unregister_blkdev(tr->major, tr->name);
mutex_unlock(&mtd_table_mutex); mutex_unlock(&mtd_table_mutex);
kfree(tr->blkcore_priv);
BUG_ON(!list_empty(&tr->devs)); BUG_ON(!list_empty(&tr->devs));
return 0; return 0;
} }
......
...@@ -19,15 +19,15 @@ ...@@ -19,15 +19,15 @@
#include <linux/mutex.h> #include <linux/mutex.h>
static struct mtdblk_dev { struct mtdblk_dev {
struct mtd_info *mtd; struct mtd_blktrans_dev mbd;
int count; int count;
struct mutex cache_mutex; struct mutex cache_mutex;
unsigned char *cache_data; unsigned char *cache_data;
unsigned long cache_offset; unsigned long cache_offset;
unsigned int cache_size; unsigned int cache_size;
enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
} *mtdblks[MAX_MTD_DEVICES]; };
static struct mutex mtdblks_lock; static struct mutex mtdblks_lock;
...@@ -98,7 +98,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos, ...@@ -98,7 +98,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos,
static int write_cached_data (struct mtdblk_dev *mtdblk) static int write_cached_data (struct mtdblk_dev *mtdblk)
{ {
struct mtd_info *mtd = mtdblk->mtd; struct mtd_info *mtd = mtdblk->mbd.mtd;
int ret; int ret;
if (mtdblk->cache_state != STATE_DIRTY) if (mtdblk->cache_state != STATE_DIRTY)
...@@ -128,7 +128,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) ...@@ -128,7 +128,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk)
static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
int len, const char *buf) int len, const char *buf)
{ {
struct mtd_info *mtd = mtdblk->mtd; struct mtd_info *mtd = mtdblk->mbd.mtd;
unsigned int sect_size = mtdblk->cache_size; unsigned int sect_size = mtdblk->cache_size;
size_t retlen; size_t retlen;
int ret; int ret;
...@@ -198,7 +198,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, ...@@ -198,7 +198,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
int len, char *buf) int len, char *buf)
{ {
struct mtd_info *mtd = mtdblk->mtd; struct mtd_info *mtd = mtdblk->mbd.mtd;
unsigned int sect_size = mtdblk->cache_size; unsigned int sect_size = mtdblk->cache_size;
size_t retlen; size_t retlen;
int ret; int ret;
...@@ -244,16 +244,16 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, ...@@ -244,16 +244,16 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
static int mtdblock_readsect(struct mtd_blktrans_dev *dev, static int mtdblock_readsect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf) unsigned long block, char *buf)
{ {
struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; struct mtdblk_dev *mtdblk = container_of(dev, struct mtdblk_dev, mbd);
return do_cached_read(mtdblk, block<<9, 512, buf); return do_cached_read(mtdblk, block<<9, 512, buf);
} }
static int mtdblock_writesect(struct mtd_blktrans_dev *dev, static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf) unsigned long block, char *buf)
{ {
struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; struct mtdblk_dev *mtdblk = container_of(dev, struct mtdblk_dev, mbd);
if (unlikely(!mtdblk->cache_data && mtdblk->cache_size)) { if (unlikely(!mtdblk->cache_data && mtdblk->cache_size)) {
mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); mtdblk->cache_data = vmalloc(mtdblk->mbd.mtd->erasesize);
if (!mtdblk->cache_data) if (!mtdblk->cache_data)
return -EINTR; return -EINTR;
/* -EINTR is not really correct, but it is the best match /* -EINTR is not really correct, but it is the best match
...@@ -266,37 +266,26 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev, ...@@ -266,37 +266,26 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
static int mtdblock_open(struct mtd_blktrans_dev *mbd) static int mtdblock_open(struct mtd_blktrans_dev *mbd)
{ {
struct mtdblk_dev *mtdblk; struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
struct mtd_info *mtd = mbd->mtd;
int dev = mbd->devnum;
DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
mutex_lock(&mtdblks_lock); mutex_lock(&mtdblks_lock);
if (mtdblks[dev]) { if (mtdblk->count) {
mtdblks[dev]->count++; mtdblk->count++;
mutex_unlock(&mtdblks_lock); mutex_unlock(&mtdblks_lock);
return 0; return 0;
} }
/* OK, it's not open. Create cache info for it */ /* OK, it's not open. Create cache info for it */
mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
if (!mtdblk) {
mutex_unlock(&mtdblks_lock);
return -ENOMEM;
}
mtdblk->count = 1; mtdblk->count = 1;
mtdblk->mtd = mtd;
mutex_init(&mtdblk->cache_mutex); mutex_init(&mtdblk->cache_mutex);
mtdblk->cache_state = STATE_EMPTY; mtdblk->cache_state = STATE_EMPTY;
if ( !(mtdblk->mtd->flags & MTD_NO_ERASE) && mtdblk->mtd->erasesize) { if (!(mbd->mtd->flags & MTD_NO_ERASE) && mbd->mtd->erasesize) {
mtdblk->cache_size = mtdblk->mtd->erasesize; mtdblk->cache_size = mbd->mtd->erasesize;
mtdblk->cache_data = NULL; mtdblk->cache_data = NULL;
} }
mtdblks[dev] = mtdblk;
mutex_unlock(&mtdblks_lock); mutex_unlock(&mtdblks_lock);
DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
...@@ -306,8 +295,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) ...@@ -306,8 +295,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
static int mtdblock_release(struct mtd_blktrans_dev *mbd) static int mtdblock_release(struct mtd_blktrans_dev *mbd)
{ {
int dev = mbd->devnum; struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
struct mtdblk_dev *mtdblk = mtdblks[dev];
DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
...@@ -318,12 +306,10 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) ...@@ -318,12 +306,10 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
mutex_unlock(&mtdblk->cache_mutex); mutex_unlock(&mtdblk->cache_mutex);
if (!--mtdblk->count) { if (!--mtdblk->count) {
/* It was the last usage. Free the device */ /* It was the last usage. Free the cache */
mtdblks[dev] = NULL; if (mbd->mtd->sync)
if (mtdblk->mtd->sync) mbd->mtd->sync(mbd->mtd);
mtdblk->mtd->sync(mtdblk->mtd);
vfree(mtdblk->cache_data); vfree(mtdblk->cache_data);
kfree(mtdblk);
} }
mutex_unlock(&mtdblks_lock); mutex_unlock(&mtdblks_lock);
...@@ -335,40 +321,40 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) ...@@ -335,40 +321,40 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
static int mtdblock_flush(struct mtd_blktrans_dev *dev) static int mtdblock_flush(struct mtd_blktrans_dev *dev)
{ {
struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; struct mtdblk_dev *mtdblk = container_of(dev, struct mtdblk_dev, mbd);
mutex_lock(&mtdblk->cache_mutex); mutex_lock(&mtdblk->cache_mutex);
write_cached_data(mtdblk); write_cached_data(mtdblk);
mutex_unlock(&mtdblk->cache_mutex); mutex_unlock(&mtdblk->cache_mutex);
if (mtdblk->mtd->sync) if (dev->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd); dev->mtd->sync(dev->mtd);
return 0; return 0;
} }
static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{ {
struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL); struct mtdblk_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) if (!dev)
return; return;
dev->mtd = mtd; dev->mbd.mtd = mtd;
dev->devnum = mtd->index; dev->mbd.devnum = mtd->index;
dev->size = mtd->size >> 9; dev->mbd.size = mtd->size >> 9;
dev->tr = tr; dev->mbd.tr = tr;
if (!(mtd->flags & MTD_WRITEABLE)) if (!(mtd->flags & MTD_WRITEABLE))
dev->readonly = 1; dev->mbd.readonly = 1;
add_mtd_blktrans_dev(dev); if (add_mtd_blktrans_dev(&dev->mbd))
kfree(dev);
} }
static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
{ {
del_mtd_blktrans_dev(dev); del_mtd_blktrans_dev(dev);
kfree(dev);
} }
static struct mtd_blktrans_ops mtdblock_tr = { static struct mtd_blktrans_ops mtdblock_tr = {
......
...@@ -43,13 +43,13 @@ static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) ...@@ -43,13 +43,13 @@ static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
dev->tr = tr; dev->tr = tr;
dev->readonly = 1; dev->readonly = 1;
add_mtd_blktrans_dev(dev); if (add_mtd_blktrans_dev(dev))
kfree(dev);
} }
static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
{ {
del_mtd_blktrans_dev(dev); del_mtd_blktrans_dev(dev);
kfree(dev);
} }
static struct mtd_blktrans_ops mtdblock_tr = { static struct mtd_blktrans_ops mtdblock_tr = {
......
...@@ -15,12 +15,15 @@ ...@@ -15,12 +15,15 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/mount.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h> #include <linux/mtd/compatmac.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define MTD_INODE_FS_MAGIC 0x11307854
static struct vfsmount *mtd_inode_mnt __read_mostly;
/* /*
* Data structure to hold the pointer to the mtd device as well * Data structure to hold the pointer to the mtd device as well
...@@ -28,6 +31,7 @@ ...@@ -28,6 +31,7 @@
*/ */
struct mtd_file_info { struct mtd_file_info {
struct mtd_info *mtd; struct mtd_info *mtd;
struct inode *ino;
enum mtd_file_modes mode; enum mtd_file_modes mode;
}; };
...@@ -64,12 +68,10 @@ static int mtd_open(struct inode *inode, struct file *file) ...@@ -64,12 +68,10 @@ static int mtd_open(struct inode *inode, struct file *file)
int ret = 0; int ret = 0;
struct mtd_info *mtd; struct mtd_info *mtd;
struct mtd_file_info *mfi; struct mtd_file_info *mfi;
struct inode *mtd_ino;
DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n"); DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
if (devnum >= MAX_MTD_DEVICES)
return -ENODEV;
/* You can't open the RO devices RW */ /* You can't open the RO devices RW */
if ((file->f_mode & FMODE_WRITE) && (minor & 1)) if ((file->f_mode & FMODE_WRITE) && (minor & 1))
return -EACCES; return -EACCES;
...@@ -88,11 +90,23 @@ static int mtd_open(struct inode *inode, struct file *file) ...@@ -88,11 +90,23 @@ static int mtd_open(struct inode *inode, struct file *file)
goto out; goto out;
} }
if (mtd->backing_dev_info) mtd_ino = iget_locked(mtd_inode_mnt->mnt_sb, devnum);
file->f_mapping->backing_dev_info = mtd->backing_dev_info; if (!mtd_ino) {
put_mtd_device(mtd);
ret = -ENOMEM;
goto out;
}
if (mtd_ino->i_state & I_NEW) {
mtd_ino->i_private = mtd;
mtd_ino->i_mode = S_IFCHR;
mtd_ino->i_data.backing_dev_info = mtd->backing_dev_info;
unlock_new_inode(mtd_ino);
}
file->f_mapping = mtd_ino->i_mapping;
/* You can't open it RW if it's not a writeable device */ /* You can't open it RW if it's not a writeable device */
if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
iput(mtd_ino);
put_mtd_device(mtd); put_mtd_device(mtd);
ret = -EACCES; ret = -EACCES;
goto out; goto out;
...@@ -100,10 +114,12 @@ static int mtd_open(struct inode *inode, struct file *file) ...@@ -100,10 +114,12 @@ static int mtd_open(struct inode *inode, struct file *file)
mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
if (!mfi) { if (!mfi) {
iput(mtd_ino);
put_mtd_device(mtd); put_mtd_device(mtd);
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
mfi->ino = mtd_ino;
mfi->mtd = mtd; mfi->mtd = mtd;
file->private_data = mfi; file->private_data = mfi;
...@@ -125,6 +141,8 @@ static int mtd_close(struct inode *inode, struct file *file) ...@@ -125,6 +141,8 @@ static int mtd_close(struct inode *inode, struct file *file)
if ((file->f_mode & FMODE_WRITE) && mtd->sync) if ((file->f_mode & FMODE_WRITE) && mtd->sync)
mtd->sync(mtd); mtd->sync(mtd);
iput(mfi->ino);
put_mtd_device(mtd); put_mtd_device(mtd);
file->private_data = NULL; file->private_data = NULL;
kfree(mfi); kfree(mfi);
...@@ -373,7 +391,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, ...@@ -373,7 +391,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
if (!mtd->write_oob) if (!mtd->write_oob)
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
else else
ret = access_ok(VERIFY_READ, ptr, length) ? 0 : EFAULT; ret = access_ok(VERIFY_READ, ptr, length) ? 0 : -EFAULT;
if (ret) if (ret)
return ret; return ret;
...@@ -482,7 +500,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, ...@@ -482,7 +500,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
{ {
uint32_t ur_idx; uint32_t ur_idx;
struct mtd_erase_region_info *kr; struct mtd_erase_region_info *kr;
struct region_info_user *ur = (struct region_info_user *) argp; struct region_info_user __user *ur = argp;
if (get_user(ur_idx, &(ur->regionindex))) if (get_user(ur_idx, &(ur->regionindex)))
return -EFAULT; return -EFAULT;
...@@ -954,22 +972,81 @@ static const struct file_operations mtd_fops = { ...@@ -954,22 +972,81 @@ static const struct file_operations mtd_fops = {
#endif #endif
}; };
static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data,
struct vfsmount *mnt)
{
return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC,
mnt);
}
static struct file_system_type mtd_inodefs_type = {
.name = "mtd_inodefs",
.get_sb = mtd_inodefs_get_sb,
.kill_sb = kill_anon_super,
};
static void mtdchar_notify_add(struct mtd_info *mtd)
{
}
static void mtdchar_notify_remove(struct mtd_info *mtd)
{
struct inode *mtd_ino = ilookup(mtd_inode_mnt->mnt_sb, mtd->index);
if (mtd_ino) {
/* Destroy the inode if it exists */
mtd_ino->i_nlink = 0;
iput(mtd_ino);
}
}
static struct mtd_notifier mtdchar_notifier = {
.add = mtdchar_notify_add,
.remove = mtdchar_notify_remove,
};
static int __init init_mtdchar(void) static int __init init_mtdchar(void)
{ {
int status; int ret;
status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS,
if (status < 0) { "mtd", &mtd_fops);
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", if (ret < 0) {
MTD_CHAR_MAJOR); pr_notice("Can't allocate major number %d for "
"Memory Technology Devices.\n", MTD_CHAR_MAJOR);
return ret;
} }
return status; ret = register_filesystem(&mtd_inodefs_type);
if (ret) {
pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret);
goto err_unregister_chdev;
}
mtd_inode_mnt = kern_mount(&mtd_inodefs_type);
if (IS_ERR(mtd_inode_mnt)) {
ret = PTR_ERR(mtd_inode_mnt);
pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret);
goto err_unregister_filesystem;
}
register_mtd_user(&mtdchar_notifier);
return ret;
err_unregister_filesystem:
unregister_filesystem(&mtd_inodefs_type);
err_unregister_chdev:
__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
return ret;
} }
static void __exit cleanup_mtdchar(void) static void __exit cleanup_mtdchar(void)
{ {
unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); unregister_mtd_user(&mtdchar_notifier);
mntput(mtd_inode_mnt);
unregister_filesystem(&mtd_inodefs_type);
__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
} }
module_init(init_mtdchar); module_init(init_mtdchar);
......
...@@ -183,10 +183,9 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs, ...@@ -183,10 +183,9 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
} }
/* make a copy of vecs */ /* make a copy of vecs */
vecs_copy = kmalloc(sizeof(struct kvec) * count, GFP_KERNEL); vecs_copy = kmemdup(vecs, sizeof(struct kvec) * count, GFP_KERNEL);
if (!vecs_copy) if (!vecs_copy)
return -ENOMEM; return -ENOMEM;
memcpy(vecs_copy, vecs, sizeof(struct kvec) * count);
entry_low = 0; entry_low = 0;
for (i = 0; i < concat->num_subdev; i++) { for (i = 0; i < concat->num_subdev; i++) {
......
此差异已折叠。
...@@ -8,4 +8,9 @@ ...@@ -8,4 +8,9 @@
should not use them for _anything_ else */ should not use them for _anything_ else */
extern struct mutex mtd_table_mutex; extern struct mutex mtd_table_mutex;
extern struct mtd_info *mtd_table[MAX_MTD_DEVICES]; extern struct mtd_info *__mtd_next_device(int i);
#define mtd_for_each_device(mtd) \
for ((mtd) = __mtd_next_device(0); \
(mtd) != NULL; \
(mtd) = __mtd_next_device(mtd->index + 1))
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册