Fix locking and simplify some error path.

This commit is contained in:
ahoka 2011-04-10 12:48:09 +00:00
parent ed194e826a
commit 4e870ad59c
2 changed files with 52 additions and 32 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: nand.c,v 1.7 2011/04/04 14:25:10 ahoka Exp $ */
/* $NetBSD: nand.c,v 1.8 2011/04/10 12:48:09 ahoka Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@ -34,7 +34,7 @@
/* Common driver for NAND chips implementing the ONFI 2.2 specification */
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nand.c,v 1.7 2011/04/04 14:25:10 ahoka Exp $");
__KERNEL_RCSID(0, "$NetBSD: nand.c,v 1.8 2011/04/10 12:48:09 ahoka Exp $");
#include "locators.h"
@ -1050,7 +1050,7 @@ nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
const uint8_t *bufp;
flash_off_t addr;
size_t left, count;
int error, i;
int error = 0, i;
first = offset & chip->nc_page_mask;
firstoff = offset & ~chip->nc_page_mask;
@ -1061,26 +1061,30 @@ nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
addr = first;
*retlen = 0;
mutex_enter(&sc->sc_device_lock);
if (count == 1) {
if (nand_isbad(self, addr)) {
aprint_error_dev(self,
"nand_flash_write_unaligned: "
"bad block encountered\n");
return EIO;
error = EIO;
goto out;
}
error = nand_read_page(self, addr, chip->nc_page_cache);
if (error)
return error;
if (error) {
goto out;
}
memcpy(chip->nc_page_cache + firstoff, buf, len);
error = nand_program_page(self, addr, chip->nc_page_cache);
if (error)
return error;
if (error) {
goto out;
}
*retlen = len;
return 0;
goto out;
}
bufp = buf;
@ -1091,14 +1095,16 @@ nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
aprint_error_dev(self,
"nand_flash_write_unaligned: "
"bad block encountered\n");
return EIO;
error = EIO;
goto out;
}
if (i == 0) {
error = nand_read_page(self,
addr, chip->nc_page_cache);
if (error)
return error;
if (error) {
goto out;
}
memcpy(chip->nc_page_cache + firstoff,
bufp, chip->nc_page_size - firstoff);
@ -1106,8 +1112,9 @@ nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
printf("program page: %s: %d\n", __FILE__, __LINE__);
error = nand_program_page(self,
addr, chip->nc_page_cache);
if (error)
return error;
if (error) {
goto out;
}
bufp += chip->nc_page_size - firstoff;
left -= chip->nc_page_size - firstoff;
@ -1116,15 +1123,17 @@ nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
} else if (i == count - 1) {
error = nand_read_page(self,
addr, chip->nc_page_cache);
if (error)
return error;
if (error) {
goto out;
}
memcpy(chip->nc_page_cache, bufp, left);
error = nand_program_page(self,
addr, chip->nc_page_cache);
if (error)
return error;
if (error) {
goto out;
}
*retlen += left;
KASSERT(left < chip->nc_page_size);
@ -1138,8 +1147,9 @@ nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
KASSERT(left > chip->nc_page_size);
error = nand_program_page(self, addr, bufp);
if (error)
return error;
if (error) {
goto out;
}
bufp += chip->nc_page_size;
left -= chip->nc_page_size;
@ -1150,8 +1160,10 @@ nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
}
KASSERT(*retlen == len);
out:
mutex_exit(&sc->sc_device_lock);
return 0;
return error;
}
int
@ -1198,8 +1210,9 @@ nand_flash_write(device_t self, flash_off_t offset, size_t len, size_t *retlen,
}
error = nand_program_page(self, addr, bufp);
if (error)
if (error) {
goto out;
}
addr += chip->nc_page_size;
bufp += chip->nc_page_size;
@ -1240,8 +1253,9 @@ nand_flash_read_unaligned(device_t self, size_t offset,
mutex_enter(&sc->sc_device_lock);
if (count == 1) {
error = nand_read_page(self, addr, chip->nc_page_cache);
if (error)
if (error) {
goto out;
}
memcpy(bufp, chip->nc_page_cache + firstoff, len);
@ -1251,8 +1265,9 @@ nand_flash_read_unaligned(device_t self, size_t offset,
for (i = 0; i < count && left != 0; i++) {
error = nand_read_page(self, addr, chip->nc_page_cache);
if (error)
if (error) {
goto out;
}
if (i == 0) {
memcpy(bufp, chip->nc_page_cache + firstoff,
@ -1415,7 +1430,7 @@ nand_flash_erase(device_t self,
struct nand_softc *sc = device_private(self);
struct nand_chip *chip = &sc->sc_chip;
flash_off_t addr;
int error;
int error = 0;
if (ei->ei_addr < 0 || ei->ei_len < chip->nc_block_size)
return EINVAL;
@ -1448,17 +1463,18 @@ nand_flash_erase(device_t self,
addr = ei->ei_addr;
while (addr < ei->ei_addr + ei->ei_len) {
if (nand_isbad(self, addr)) {
mutex_exit(&sc->sc_device_lock);
aprint_error_dev(self, "bad block encountered\n");
ei->ei_state = FLASH_ERASE_FAILED;
return EIO;
error = EIO;
goto out;
}
error = nand_erase_block(self, addr);
if (error) {
mutex_exit(&sc->sc_device_lock);
ei->ei_state = FLASH_ERASE_FAILED;
return error;
goto out;
}
addr += chip->nc_block_size;
@ -1466,10 +1482,15 @@ nand_flash_erase(device_t self,
mutex_exit(&sc->sc_device_lock);
ei->ei_state = FLASH_ERASE_DONE;
if (ei->ei_callback != NULL)
if (ei->ei_callback != NULL) {
ei->ei_callback(ei);
}
return 0;
out:
mutex_exit(&sc->sc_device_lock);
return error;
}
static int

View File

@ -1,4 +1,4 @@
/* $NetBSD: nand.h,v 1.5 2011/04/04 14:25:10 ahoka Exp $ */
/* $NetBSD: nand.h,v 1.6 2011/04/10 12:48:09 ahoka Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@ -44,7 +44,6 @@
#include <dev/nand/onfi.h>
#include <dev/flash/flash.h>
//#define NAND_DEBUG 1
#ifdef NAND_DEBUG
#define DPRINTF(x) if (nanddebug) printf x
#define DPRINTFN(n,x) if (nanddebug>(n)) printf x