From 6071239ef1947914892601e36785c7b1cf8b7dd4 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 15 May 2008 10:10:37 -0600 Subject: mtdchar: cdev lock_kernel() pushdown Signed-off-by: Jonathan Corbet --- drivers/mtd/mtdchar.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 5d3ac512ce16..129d429cd2da 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -86,6 +87,7 @@ static int mtd_open(struct inode *inode, struct file *file) { int minor = iminor(inode); int devnum = minor >> 1; + int ret = 0; struct mtd_info *mtd; struct mtd_file_info *mfi; @@ -98,31 +100,39 @@ static int mtd_open(struct inode *inode, struct file *file) if ((file->f_mode & 2) && (minor & 1)) return -EACCES; + lock_kernel(); mtd = get_mtd_device(NULL, devnum); - if (IS_ERR(mtd)) - return PTR_ERR(mtd); + if (IS_ERR(mtd)) { + ret = PTR_ERR(mtd); + goto out; + } if (MTD_ABSENT == mtd->type) { put_mtd_device(mtd); - return -ENODEV; + ret = -ENODEV; + goto out; } /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) { put_mtd_device(mtd); - return -EACCES; + ret = -EACCES; + goto out; } mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); if (!mfi) { put_mtd_device(mtd); - return -ENOMEM; + ret = -ENOMEM; + goto out; } mfi->mtd = mtd; file->private_data = mfi; - return 0; +out: + unlock_kernel(); + return ret; } /* mtd_open */ /*====================================================================*/ -- cgit v1.2.3-58-ga151 From 72b67048f5dac18fd6494e3d3bff7e54840e8761 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 15 May 2008 10:15:38 -0600 Subject: UBI: cdev lock_kernel() pushdown Signed-off-by: Jonathan Corbet --- drivers/mtd/ubi/cdev.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 9d6aae5449b6..89193ba9451e 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -103,9 +104,12 @@ static int vol_cdev_open(struct inode *inode, struct file *file) struct ubi_volume_desc *desc; int vol_id = iminor(inode) - 1, mode, ubi_num; + lock_kernel(); ubi_num = ubi_major2num(imajor(inode)); - if (ubi_num < 0) + if (ubi_num < 0) { + unlock_kernel(); return ubi_num; + } if (file->f_mode & FMODE_WRITE) mode = UBI_READWRITE; @@ -115,6 +119,7 @@ static int vol_cdev_open(struct inode *inode, struct file *file) dbg_msg("open volume %d, mode %d", vol_id, mode); desc = ubi_open_volume(ubi_num, vol_id, mode); + unlock_kernel(); if (IS_ERR(desc)) return PTR_ERR(desc); -- cgit v1.2.3-58-ga151 From c5081d5f4775b2a3f858f91151bbf9163e473075 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 19 Jun 2008 20:12:34 +0200 Subject: pcmcia: simplify pccard_validate_cis As cisinfo_t only contains one unsigned_int, pccard_validate_cis can be simplified by passing that around directly. Signed-off-by: Dominik Brodowski --- drivers/mtd/maps/pcmciamtd.c | 5 +---- drivers/pcmcia/cistpl.c | 15 +++++++++------ drivers/pcmcia/ds.c | 7 +++---- drivers/pcmcia/pcmcia_ioctl.c | 2 +- drivers/pcmcia/rsrc_nonstatic.c | 11 ++++++----- drivers/pcmcia/socket_sysfs.c | 6 +++--- include/pcmcia/cistpl.h | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 1912d968718b..00530f9bf4a7 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -498,17 +498,14 @@ static int pcmciamtd_config(struct pcmcia_device *link) int i; config_info_t t; static char *probes[] = { "jedec_probe", "cfi_probe" }; - cisinfo_t cisinfo; int new_name = 0; DEBUG(3, "link=0x%p", link); DEBUG(2, "Validating CIS"); - ret = pcmcia_validate_cis(link, &cisinfo); + ret = pcmcia_validate_cis(link, NULL); if(ret != CS_SUCCESS) { cs_error(link, GetTupleData, ret); - } else { - DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains); } card_settings(dev, link, &new_name); diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 36379535f9da..0996ca253f28 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -1439,10 +1439,11 @@ EXPORT_SYMBOL(pccard_read_tuple); ======================================================================*/ -int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info) +int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *info) { tuple_t *tuple; cisparse_t *p; + unsigned int count = 0; int ret, reserved, dev_ok = 0, ident_ok = 0; if (!s) @@ -1457,7 +1458,7 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_ return CS_OUT_OF_RESOURCE; } - info->Chains = reserved = 0; + count = reserved = 0; tuple->DesiredTuple = RETURN_FIRST_TUPLE; tuple->Attributes = TUPLE_RETURN_COMMON; ret = pccard_get_first_tuple(s, function, tuple); @@ -1482,7 +1483,7 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_ if (!dev_ok && !ident_ok) goto done; - for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) { + for (count = 1; count < MAX_TUPLES; count++) { ret = pccard_get_next_tuple(s, function, tuple); if (ret != CS_SUCCESS) break; if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) || @@ -1490,11 +1491,13 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_ ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff))) reserved++; } - if ((info->Chains == MAX_TUPLES) || (reserved > 5) || - ((!dev_ok || !ident_ok) && (info->Chains > 10))) - info->Chains = 0; + if ((count) || (reserved > 5) || + ((!dev_ok || !ident_ok) && (count > 10))) + count = 0; done: + if (info) + *info = count; kfree(tuple); kfree(p); return CS_SUCCESS; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index e40775443d04..0f56cb5a30be 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -741,9 +741,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f static int pcmcia_card_add(struct pcmcia_socket *s) { - cisinfo_t cisinfo; cistpl_longlink_mfc_t mfc; - unsigned int no_funcs, i; + unsigned int no_funcs, i, no_chains; int ret = 0; if (!(s->resource_setup_done)) { @@ -757,8 +756,8 @@ static int pcmcia_card_add(struct pcmcia_socket *s) return -EAGAIN; /* try again, but later... */ } - ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo); - if (ret || !cisinfo.Chains) { + ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains); + if (ret || !no_chains) { ds_dbg(0, "invalid CIS or invalid resources\n"); return -ENODEV; } diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 758ece8dc362..1efc74fef148 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -735,7 +735,7 @@ static int ds_ioctl(struct inode * inode, struct file * file, mutex_lock(&s->skt_mutex); pcmcia_validate_mem(s); mutex_unlock(&s->skt_mutex); - ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo); + ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo.Chains); break; case DS_SUSPEND_CARD: ret = pcmcia_suspend_card(s); diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 162693480ed0..70d2e010e654 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -261,21 +261,22 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base, ======================================================================*/ /* Validation function for cards with a valid CIS */ -static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info) +static int readable(struct pcmcia_socket *s, struct resource *res, + unsigned int *count) { int ret = -1; s->cis_mem.res = res; s->cis_virt = ioremap(res->start, s->map_size); if (s->cis_virt) { - ret = pccard_validate_cis(s, BIND_FN_ALL, info); + ret = pccard_validate_cis(s, BIND_FN_ALL, count); /* invalidate mapping and CIS cache */ iounmap(s->cis_virt); s->cis_virt = NULL; destroy_cis_cache(s); } s->cis_mem.res = NULL; - if ((ret != 0) || (info->Chains == 0)) + if ((ret != 0) || (count == 0)) return 0; return 1; } @@ -316,7 +317,7 @@ static int cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size) { struct resource *res1, *res2; - cisinfo_t info1, info2; + unsigned int info1, info2; int ret = 0; res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe"); @@ -330,7 +331,7 @@ cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size) free_region(res2); free_region(res1); - return (ret == 2) && (info1.Chains == info2.Chains); + return (ret == 2) && (info1 == info2); } static int diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 562384d6f321..ff079987db1d 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -293,7 +293,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, count = 0; else { struct pcmcia_socket *s; - cisinfo_t cisinfo; + unsigned int chains; if (off + count > size) count = size - off; @@ -302,9 +302,9 @@ static ssize_t pccard_show_cis(struct kobject *kobj, if (!(s->state & SOCKET_PRESENT)) return -ENODEV; - if (pccard_validate_cis(s, BIND_FN_ALL, &cisinfo)) + if (pccard_validate_cis(s, BIND_FN_ALL, &chains)) return -EIO; - if (!cisinfo.Chains) + if (!chains) return -ENODATA; count = pccard_extract_cis(s, buf, off, count); diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index d3bbb19caf81..e2e10c1e9a06 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h @@ -595,7 +595,7 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse); -int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info); +int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *count); /* ... but use these wrappers instead */ #define pcmcia_get_first_tuple(p_dev, tuple) \ -- cgit v1.2.3-58-ga151 From ae49ec9258b1ba0456f5d2e9024d0e4742a0188b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Jun 2008 20:49:41 +0200 Subject: pcmcia: remove unused bulkmem.h The code in include/pcmcia/bulkmem.h was only kept for compatibility reasons. Therefore, move the remaining region_info_t definition to ds.h [linux@dominikbrodowski.net: do not modify the IOCTL, move definition to ds.h, and update changelog] Signed-off-by: Magnus Damm Signed-off-by: Dominik Brodowski --- drivers/mtd/ftl.c | 4 ---- drivers/pcmcia/au1000_generic.h | 1 - drivers/pcmcia/au1000_pb1x00.c | 1 - drivers/pcmcia/au1000_xxs1500.c | 1 - drivers/pcmcia/cardbus.c | 1 - drivers/pcmcia/cistpl.c | 1 - drivers/pcmcia/cs.c | 1 - drivers/pcmcia/cs_internal.h | 12 ------------ drivers/pcmcia/hd64465_ss.c | 1 - drivers/pcmcia/pcmcia_resource.c | 1 - drivers/pcmcia/pxa2xx_base.c | 1 - drivers/pcmcia/rsrc_nonstatic.c | 1 - drivers/pcmcia/soc_common.h | 1 - drivers/pcmcia/socket_sysfs.c | 1 - include/pcmcia/bulkmem.h | 41 ---------------------------------------- include/pcmcia/ds.h | 19 ++++++++++++++++++- include/pcmcia/ss.h | 1 - 17 files changed, 18 insertions(+), 71 deletions(-) delete mode 100644 include/pcmcia/bulkmem.h (limited to 'drivers/mtd') diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 4a79b187b568..5c29872184e6 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -130,10 +130,6 @@ typedef struct partition_t { u_int16_t DataUnits; u_int32_t BlocksPerUnit; erase_unit_header_t header; -#if 0 - region_info_t region; - memory_handle_t handle; -#endif } partition_t; /* Partition state flags */ diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h index c62437df175e..a53ef5902518 100644 --- a/drivers/pcmcia/au1000_generic.h +++ b/drivers/pcmcia/au1000_generic.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index 157e41423a0a..aa1cd4d3aa29 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c index c78ed5347510..8a9b18cee847 100644 --- a/drivers/pcmcia/au1000_xxs1500.c +++ b/drivers/pcmcia/au1000_xxs1500.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index fb2f38dc92c5..1c104a7b29c7 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 0996ca253f28..9fcff0c33619 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 6bb1bb5db9c4..b6cd7c9a92bb 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index e7d5d141f24d..0a9e420defda 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -26,18 +26,6 @@ #define CLIENT_WIN_REQ(i) (0x1<<(i)) #define CLIENT_CARDBUS 0x8000 -#define REGION_MAGIC 0xE3C9 -typedef struct region_t { - u_short region_magic; - u_short state; - dev_info_t dev_info; - struct pcmcia_device *mtd; - u_int MediaID; - region_info_t info; -} region_t; - -#define REGION_STALE 0x01 - /* Each card function gets one of these guys */ typedef struct config_t { struct kref ref; diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c index 6045e4b69531..fb2bc1fb015d 100644 --- a/drivers/pcmcia/hd64465_ss.c +++ b/drivers/pcmcia/hd64465_ss.c @@ -46,7 +46,6 @@ #include #include #include -#include #include "cs_internal.h" #define MODNAME "hd64465_ss" diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 78af59415930..2d3e3fe66ee7 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 9414163c78e7..ccfdf1969a7f 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -33,7 +33,6 @@ #include #include -#include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 70d2e010e654..d0c1d63d1891 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h index 1edc1da9d353..91ef6a0da3ab 100644 --- a/drivers/pcmcia/soc_common.h +++ b/drivers/pcmcia/soc_common.h @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "cs_internal.h" diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index ff079987db1d..bb1653f2ed82 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h deleted file mode 100644 index 6bc7472293b2..000000000000 --- a/include/pcmcia/bulkmem.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * bulkmem.h -- Definitions for bulk memory services - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * (C) 1999 David A. Hinds - */ - -#ifndef _LINUX_BULKMEM_H -#define _LINUX_BULKMEM_H - -/* For GetFirstRegion and GetNextRegion */ -typedef struct region_info_t { - u_int Attributes; - u_int CardOffset; - u_int RegionSize; - u_int AccessSpeed; - u_int BlockSize; - u_int PartMultiple; - u_char JedecMfr, JedecInfo; - memory_handle_t next; -} region_info_t; - -#define REGION_TYPE 0x0001 -#define REGION_TYPE_CM 0x0000 -#define REGION_TYPE_AM 0x0001 -#define REGION_PREFETCH 0x0008 -#define REGION_CACHEABLE 0x0010 -#define REGION_BAR_MASK 0xe000 -#define REGION_BAR_SHIFT 13 - -int pcmcia_get_first_region(struct pcmcia_device *handle, region_info_t *rgn); -int pcmcia_get_next_region(struct pcmcia_device *handle, region_info_t *rgn); - -#endif /* _LINUX_BULKMEM_H */ diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index f047a1fd64f8..b316027c853d 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -20,7 +20,6 @@ #include #endif -#include #include #include @@ -51,6 +50,24 @@ typedef struct mtd_info_t { u_int CardOffset; } mtd_info_t; +typedef struct region_info_t { + u_int Attributes; + u_int CardOffset; + u_int RegionSize; + u_int AccessSpeed; + u_int BlockSize; + u_int PartMultiple; + u_char JedecMfr, JedecInfo; + memory_handle_t next; +} region_info_t; +#define REGION_TYPE 0x0001 +#define REGION_TYPE_CM 0x0000 +#define REGION_TYPE_AM 0x0001 +#define REGION_PREFETCH 0x0008 +#define REGION_CACHEABLE 0x0010 +#define REGION_BAR_MASK 0xe000 +#define REGION_BAR_SHIFT 13 + typedef union ds_ioctl_arg_t { adjust_t adjust; config_info_t config; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index e6a2338b370f..ed919dd9bb5c 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -21,7 +21,6 @@ #include #include -#include #ifdef CONFIG_CARDBUS #include #endif -- cgit v1.2.3-58-ga151 From 4aeba0134f1e54cfd881e118b039ab6ed8b99126 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 20 Jun 2008 13:24:31 +0200 Subject: pcmcia: (re)move {pcmcia,pccard}_get_status Except for one debug message in a driver marked BROKEN, pcmcia_get_status is only used by the ioctl. Therefore, move it to pcmcia_ioctl.c and unexport it. Signed-off-by: Dominik Brodowski --- drivers/mtd/maps/pcmciamtd.c | 4 +-- drivers/pcmcia/cs_internal.h | 1 - drivers/pcmcia/pcmcia_ioctl.c | 61 +++++++++++++++++++++++++++++++++++ drivers/pcmcia/pcmcia_resource.c | 68 ---------------------------------------- include/pcmcia/cs.h | 1 - 5 files changed, 62 insertions(+), 73 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 00530f9bf4a7..0cc31675aeb9 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -560,9 +560,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); /* Get write protect status */ - CS_CHECK(GetStatus, pcmcia_get_status(link, &status)); - DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", - status.CardState, (unsigned long)link->win); + DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win); dev->win_base = ioremap(req.Base, req.Size); if(!dev->win_base) { err("ioremap(%lu, %u) failed", req.Base, req.Size); diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 0a9e420defda..63dc1a28bda2 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -118,7 +118,6 @@ extern struct list_head pcmcia_socket_list; int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req); int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config); int pccard_reset_card(struct pcmcia_socket *skt); -int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status); struct pcmcia_callback{ diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 2d0521019536..afd00e7bbbef 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -224,6 +225,66 @@ static int pcmcia_adjust_resource_info(adjust_t *adj) return (ret); } +/** pccard_get_status + * + * Get the current socket state bits. We don't support the latched + * SocketState yet: I haven't seen any point for it. + */ + +static int pccard_get_status(struct pcmcia_socket *s, + struct pcmcia_device *p_dev, + cs_status_t *status) +{ + config_t *c; + int val; + + s->ops->get_status(s, &val); + status->CardState = status->SocketState = 0; + status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; + status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; + status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0; + status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0; + if (s->state & SOCKET_SUSPEND) + status->CardState |= CS_EVENT_PM_SUSPEND; + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + + c = (p_dev) ? p_dev->function_config : NULL; + + if ((c != NULL) && (c->state & CONFIG_LOCKED) && + (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { + u_char reg; + if (c->CardValues & PRESENT_PIN_REPLACE) { + pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); + status->CardState |= + (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; + status->CardState |= + (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0; + status->CardState |= + (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0; + status->CardState |= + (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0; + } else { + /* No PRR? Then assume we're always ready */ + status->CardState |= CS_EVENT_READY_CHANGE; + } + if (c->CardValues & PRESENT_EXT_STATUS) { + pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); + status->CardState |= + (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; + } + return CS_SUCCESS; + } + status->CardState |= + (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0; + status->CardState |= + (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0; + status->CardState |= + (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0; + status->CardState |= + (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; + return CS_SUCCESS; +} /* pccard_get_status */ /*====================================================================== diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index cb6b5da3f29a..4884a18cf9e6 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -309,74 +309,6 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, EXPORT_SYMBOL(pcmcia_get_window); -/** pccard_get_status - * - * Get the current socket state bits. We don't support the latched - * SocketState yet: I haven't seen any point for it. - */ - -int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, - cs_status_t *status) -{ - config_t *c; - int val; - - s->ops->get_status(s, &val); - status->CardState = status->SocketState = 0; - status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; - status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; - status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0; - status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0; - if (s->state & SOCKET_SUSPEND) - status->CardState |= CS_EVENT_PM_SUSPEND; - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - - c = (p_dev) ? p_dev->function_config : NULL; - - if ((c != NULL) && (c->state & CONFIG_LOCKED) && - (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { - u_char reg; - if (c->CardValues & PRESENT_PIN_REPLACE) { - pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); - status->CardState |= - (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; - status->CardState |= - (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0; - status->CardState |= - (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0; - status->CardState |= - (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0; - } else { - /* No PRR? Then assume we're always ready */ - status->CardState |= CS_EVENT_READY_CHANGE; - } - if (c->CardValues & PRESENT_EXT_STATUS) { - pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); - status->CardState |= - (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; - } - return CS_SUCCESS; - } - status->CardState |= - (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0; - status->CardState |= - (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0; - status->CardState |= - (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0; - status->CardState |= - (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; - return CS_SUCCESS; -} /* pccard_get_status */ - -int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status) -{ - return pccard_get_status(p_dev->socket, p_dev, status); -} -EXPORT_SYMBOL(pcmcia_get_status); - - - /** pcmcia_get_mem_page * * Change the card address of an already open memory window. diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 7b67ca9771ce..45d84b275789 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -373,7 +373,6 @@ struct pcmcia_socket; int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg); int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config); -int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status); int pcmcia_get_mem_page(window_handle_t win, memreq_t *req); int pcmcia_map_mem_page(window_handle_t win, memreq_t *req); int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); -- cgit v1.2.3-58-ga151 From f4db56ffd43a810424866fac6de9a32486415316 Mon Sep 17 00:00:00 2001 From: Saeed Bishara Date: Sun, 4 May 2008 19:25:52 -1100 Subject: [MTD] orion_nand: add chip_delay parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some SoCs need a different chip_delay value. Signed-off-by: Saeed Bishara Acked-by: Jörn Engel Signed-off-by: Lennert Buytenhek Signed-off-by: Nicolas Pitre --- drivers/mtd/nand/orion_nand.c | 3 +++ include/asm-arm/plat-orion/orion_nand.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 59e05a1c50cf..ee2ac3948cd8 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -85,6 +85,9 @@ static int __init orion_nand_probe(struct platform_device *pdev) nc->cmd_ctrl = orion_nand_cmd_ctrl; nc->ecc.mode = NAND_ECC_SOFT; + if (board->chip_delay) + nc->chip_delay = board->chip_delay; + if (board->width == 16) nc->options |= NAND_BUSWIDTH_16; diff --git a/include/asm-arm/plat-orion/orion_nand.h b/include/asm-arm/plat-orion/orion_nand.h index ffd3852a0dd7..ad4ce94c1998 100644 --- a/include/asm-arm/plat-orion/orion_nand.h +++ b/include/asm-arm/plat-orion/orion_nand.h @@ -18,6 +18,7 @@ struct orion_nand_data { u8 ale; /* address line number connected to ALE */ u8 cle; /* address line number connected to CLE */ u8 width; /* buswidth */ + u8 chip_delay; }; -- cgit v1.2.3-58-ga151 From 030b15457d8069a6255579a28db196e002cb9c86 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 3 Jul 2008 12:24:41 +0300 Subject: ARM: OMAP: Change omap_cf.c and omap_nor.c to use omap_readw/writew instead of __REG Change omap_cf.c and omap_nor.c to use omap_readw/writew instead of __REG. This is needed for multi-omap in the future. Cc: David Brownell Cc: linux-pcmcia@lists.infradead.org Cc: linux-mtd@lists.infradead.org Signed-off-by: Tony Lindren --- arch/arm/mach-omap1/board-osk.c | 13 ++++++++++--- drivers/mtd/maps/omap_nor.c | 23 ++++++++++++++++------- drivers/pcmcia/omap_cf.c | 25 +++++++++++++------------ include/asm-arm/arch-omap/tc.h | 10 ++++------ 4 files changed, 43 insertions(+), 28 deletions(-) (limited to 'drivers/mtd') diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index a66505f58b15..82ec34c43bc5 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -267,13 +267,17 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = { static void __init osk_init_smc91x(void) { + u32 l; + if ((gpio_request(0, "smc_irq")) < 0) { printk("Error requesting gpio 0 for smc91x irq\n"); return; } /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ - EMIFS_CCS(1) |= 0x3; + l = omap_readl(EMIFS_CCS(1)); + l |= 0x3; + omap_writel(l, EMIFS_CCS(1)); } static void __init osk_init_cf(void) @@ -526,13 +530,16 @@ static void __init osk_mistral_init(void) { } static void __init osk_init(void) { + u32 l; + /* Workaround for wrong CS3 (NOR flash) timing * There are some U-Boot versions out there which configure * wrong CS3 memory timings. This mainly leads to CRC * or similar errors if you use NOR flash (e.g. with JFFS2) */ - if (EMIFS_CCS(3) != EMIFS_CS3_VAL) - EMIFS_CCS(3) = EMIFS_CS3_VAL; + l = omap_readl(EMIFS_CCS(3)); + if (l != EMIFS_CS3_VAL) + omap_writel(EMIFS_CS3_VAL, EMIFS_CCS(3)); osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys(); osk_flash_resource.end += SZ_32M - 1; diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index c12d8056bebd..68eec6c6c517 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c @@ -60,13 +60,22 @@ struct omapflash_info { static void omap_set_vpp(struct map_info *map, int enable) { static int count; - - if (enable) { - if (count++ == 0) - OMAP_EMIFS_CONFIG_REG |= OMAP_EMIFS_CONFIG_WP; - } else { - if (count && (--count == 0)) - OMAP_EMIFS_CONFIG_REG &= ~OMAP_EMIFS_CONFIG_WP; + u32 l; + + if (cpu_class_is_omap1()) { + if (enable) { + if (count++ == 0) { + l = omap_readl(EMIFS_CONFIG); + l |= OMAP_EMIFS_CONFIG_WP; + omap_writel(l, EMIFS_CONFIG); + } + } else { + if (count && (--count == 0)) { + l = omap_readl(EMIFS_CONFIG); + l &= ~OMAP_EMIFS_CONFIG_WP; + omap_writel(l, EMIFS_CONFIG); + } + } } } diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index 46314b420765..569b746b5731 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -38,19 +38,19 @@ #define CF_BASE 0xfffe2800 /* status; read after IRQ */ -#define CF_STATUS_REG __REG16(CF_BASE + 0x00) +#define CF_STATUS (CF_BASE + 0x00) # define CF_STATUS_BAD_READ (1 << 2) # define CF_STATUS_BAD_WRITE (1 << 1) # define CF_STATUS_CARD_DETECT (1 << 0) /* which chipselect (CS0..CS3) is used for CF (active low) */ -#define CF_CFG_REG __REG16(CF_BASE + 0x02) +#define CF_CFG (CF_BASE + 0x02) /* card reset */ -#define CF_CONTROL_REG __REG16(CF_BASE + 0x04) +#define CF_CONTROL (CF_BASE + 0x04) # define CF_CONTROL_RESET (1 << 0) -#define omap_cf_present() (!(CF_STATUS_REG & CF_STATUS_CARD_DETECT)) +#define omap_cf_present() (!(omap_readw(CF_STATUS) & CF_STATUS_CARD_DETECT)) /*--------------------------------------------------------------------------*/ @@ -139,11 +139,11 @@ omap_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s) return -EINVAL; } - control = CF_CONTROL_REG; + control = omap_readw(CF_CONTROL); if (s->flags & SS_RESET) - CF_CONTROL_REG = CF_CONTROL_RESET; + omap_writew(CF_CONTROL_RESET, CF_CONTROL); else - CF_CONTROL_REG = 0; + omap_writew(0, CF_CONTROL); pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n", driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask); @@ -270,7 +270,7 @@ static int __init omap_cf_probe(struct platform_device *pdev) omap_cfg_reg(V10_1610_CF_IREQ); omap_cfg_reg(W10_1610_CF_RESET); - CF_CFG_REG = ~(1 << seg); + omap_writew(~(1 << seg), CF_CFG); pr_info("%s: cs%d on irq %d\n", driver_name, seg, irq); @@ -279,14 +279,15 @@ static int __init omap_cf_probe(struct platform_device *pdev) * CF/PCMCIA variants... */ pr_debug("%s: cs%d, previous ccs %08x acs %08x\n", driver_name, - seg, EMIFS_CCS(seg), EMIFS_ACS(seg)); - EMIFS_CCS(seg) = 0x0004a1b3; /* synch mode 4 etc */ - EMIFS_ACS(seg) = 0x00000000; /* OE hold/setup */ + seg, omap_readl(EMIFS_CCS(seg)), omap_readl(EMIFS_ACS(seg))); + omap_writel(0x0004a1b3, EMIFS_CCS(seg)); /* synch mode 4 etc */ + omap_writel(0x00000000, EMIFS_ACS(seg)); /* OE hold/setup */ /* CF uses armxor_ck, which is "always" available */ pr_debug("%s: sts %04x cfg %04x control %04x %s\n", driver_name, - CF_STATUS_REG, CF_CFG_REG, CF_CONTROL_REG, + omap_readw(CF_STATUS), omap_readw(CF_CFG), + omap_readw(CF_CONTROL), omap_cf_present() ? "present" : "(not present)"); cf->socket.owner = THIS_MODULE; diff --git a/include/asm-arm/arch-omap/tc.h b/include/asm-arm/arch-omap/tc.h index 8ded218cbea5..65a9c82d3bf7 100644 --- a/include/asm-arm/arch-omap/tc.h +++ b/include/asm-arm/arch-omap/tc.h @@ -75,16 +75,14 @@ #ifndef __ASSEMBLER__ /* EMIF Slow Interface Configuration Register */ -#define OMAP_EMIFS_CONFIG_REG __REG32(EMIFS_CONFIG) - #define OMAP_EMIFS_CONFIG_FR (1 << 4) #define OMAP_EMIFS_CONFIG_PDE (1 << 3) #define OMAP_EMIFS_CONFIG_PWD_EN (1 << 2) #define OMAP_EMIFS_CONFIG_BM (1 << 1) #define OMAP_EMIFS_CONFIG_WP (1 << 0) -#define EMIFS_CCS(n) __REG32(EMIFS_CS0_CONFIG + (4 * (n))) -#define EMIFS_ACS(n) __REG32(EMIFS_ACS0 + (4 * (n))) +#define EMIFS_CCS(n) (EMIFS_CS0_CONFIG + (4 * (n))) +#define EMIFS_ACS(n) (EMIFS_ACS0 + (4 * (n))) /* Almost all documentation for chip and board memory maps assumes * BM is clear. Most devel boards have a switch to control booting @@ -93,13 +91,13 @@ */ static inline u32 omap_cs0_phys(void) { - return (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM) + return (omap_readl(EMIFS_CONFIG) & OMAP_EMIFS_CONFIG_BM) ? OMAP_CS3_PHYS : 0; } static inline u32 omap_cs3_phys(void) { - return (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM) + return (omap_readl(EMIFS_CONFIG) & OMAP_EMIFS_CONFIG_BM) ? 0 : OMAP_CS3_PHYS; } -- cgit v1.2.3-58-ga151 From 70eb33d67ab6982d0f9571621efb3c035b945684 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 17 Jun 2008 09:48:46 +0100 Subject: [ARM] 5105/1: CM-X270: update NAND flash driver to use gpio_lib Update CM-X270 NAND flash driver to use gpio_lib. Signed-off-by: Mike Rapoport Signed-off-by: Russell King --- drivers/mtd/nand/cmx270_nand.c | 79 +++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 32 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index cb663ef245d5..fc8529bedfdf 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c @@ -20,9 +20,11 @@ #include #include +#include #include #include +#include #include #include @@ -30,20 +32,6 @@ #define GPIO_NAND_CS (11) #define GPIO_NAND_RB (89) -/* This macro needed to ensure in-order operation of GPIO and local - * bus. Without both asm command and dummy uncached read there're - * states when NAND access is broken. I've looked for such macro(s) in - * include/asm-arm but found nothing approptiate. - * dmac_clean_range is close, but is makes cache invalidation - * unnecessary here and it cannot be used in module - */ -#define DRAIN_WB() \ - do { \ - unsigned char dummy; \ - asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); \ - dummy=*((unsigned char*)UNCACHED_ADDR); \ - } while(0) - /* MTD structure for CM-X270 board */ static struct mtd_info *cmx270_nand_mtd; @@ -103,14 +91,14 @@ static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) static inline void nand_cs_on(void) { - GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); + gpio_set_value(GPIO_NAND_CS, 0); } static void nand_cs_off(void) { - DRAIN_WB(); + dsb(); - GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); + gpio_set_value(GPIO_NAND_CS, 1); } /* @@ -122,7 +110,7 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, struct nand_chip* this = mtd->priv; unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; - DRAIN_WB(); + dsb(); if (ctrl & NAND_CTRL_CHANGE) { if ( ctrl & NAND_ALE ) @@ -139,12 +127,12 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, nand_cs_off(); } - DRAIN_WB(); + dsb(); this->IO_ADDR_W = (void __iomem*)nandaddr; if (dat != NAND_CMD_NONE) writel((dat << 16), this->IO_ADDR_W); - DRAIN_WB(); + dsb(); } /* @@ -152,9 +140,9 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, */ static int cmx270_device_ready(struct mtd_info *mtd) { - DRAIN_WB(); + dsb(); - return (GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB)); + return (gpio_get_value(GPIO_NAND_RB)); } /* @@ -168,20 +156,40 @@ static int cmx270_init(void) int mtd_parts_nb = 0; int ret; + if (!machine_is_armcore()) + return -ENODEV; + + ret = gpio_request(GPIO_NAND_CS, "NAND CS"); + if (ret) { + pr_warning("CM-X270: failed to request NAND CS gpio\n"); + return ret; + } + + gpio_direction_output(GPIO_NAND_CS, 1); + + ret = gpio_request(GPIO_NAND_RB, "NAND R/B"); + if (ret) { + pr_warning("CM-X270: failed to request NAND R/B gpio\n"); + goto err_gpio_request; + } + + gpio_direction_input(GPIO_NAND_RB); + /* Allocate memory for MTD device structure and private data */ cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!cmx270_nand_mtd) { - printk("Unable to allocate CM-X270 NAND MTD device structure.\n"); - return -ENOMEM; + pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n"); + ret = -ENOMEM; + goto err_kzalloc; } cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12); if (!cmx270_nand_io) { - printk("Unable to ioremap NAND device\n"); + pr_debug("Unable to ioremap NAND device\n"); ret = -EINVAL; - goto err1; + goto err_ioremap; } /* Get pointer to private data */ @@ -209,9 +217,9 @@ static int cmx270_init(void) /* Scan to find existence of the device */ if (nand_scan (cmx270_nand_mtd, 1)) { - printk(KERN_NOTICE "No NAND device\n"); + pr_notice("No NAND device\n"); ret = -ENXIO; - goto err2; + goto err_scan; } #ifdef CONFIG_MTD_CMDLINE_PARTS @@ -229,18 +237,22 @@ static int cmx270_init(void) } /* Register the partitions */ - printk(KERN_NOTICE "Using %s partition definition\n", part_type); + pr_notice("Using %s partition definition\n", part_type); ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); if (ret) - goto err2; + goto err_scan; /* Return happy */ return 0; -err2: +err_scan: iounmap(cmx270_nand_io); -err1: +err_ioremap: kfree(cmx270_nand_mtd); +err_kzalloc: + gpio_free(GPIO_NAND_RB); +err_gpio_request: + gpio_free(GPIO_NAND_CS); return ret; @@ -255,6 +267,9 @@ static void cmx270_cleanup(void) /* Release resources, unregister device */ nand_release(cmx270_nand_mtd); + gpio_free(GPIO_NAND_RB); + gpio_free(GPIO_NAND_CS); + iounmap(cmx270_nand_io); /* Free the MTD device structure */ -- cgit v1.2.3-58-ga151 From 9528356308ecd2fb6368472615996a8602c02964 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Fri, 11 Jul 2008 22:34:48 +0900 Subject: [MIPS] MTX-1 flash partition setup move to platform devices registration Signed-off-by: Yoichi Yuasa Acked-By: David Woodhouse Signed-off-by: Ralf Baechle --- arch/mips/au1000/mtx-1/platform.c | 51 ++++++++++++++++++++- drivers/mtd/maps/Kconfig | 7 --- drivers/mtd/maps/Makefile | 1 - drivers/mtd/maps/mtx-1_flash.c | 95 --------------------------------------- 4 files changed, 50 insertions(+), 104 deletions(-) delete mode 100644 drivers/mtd/maps/mtx-1_flash.c (limited to 'drivers/mtd') diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c index 9807be37c32f..8b5914d1241f 100644 --- a/arch/mips/au1000/mtx-1/platform.c +++ b/arch/mips/au1000/mtx-1/platform.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include static struct gpio_keys_button mtx1_gpio_button[] = { { @@ -85,10 +88,56 @@ static struct platform_device mtx1_gpio_leds = { } }; +static struct mtd_partition mtx1_mtd_partitions[] = { + { + .name = "filesystem", + .size = 0x01C00000, + .offset = 0, + }, + { + .name = "yamon", + .size = 0x00100000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "kernel", + .size = 0x002c0000, + .offset = MTDPART_OFS_APPEND, + }, + { + .name = "yamon env", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + }, +}; + +static struct physmap_flash_data mtx1_flash_data = { + .width = 4, + .nr_parts = 4, + .parts = mtx1_mtd_partitions, +}; + +static struct resource mtx1_mtd_resource = { + .start = 0x1e000000, + .end = 0x1fffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device mtx1_mtd = { + .name = "physmap-flash", + .dev = { + .platform_data = &mtx1_flash_data, + }, + .num_resources = 1, + .resource = &mtx1_mtd_resource, +}; + static struct __initdata platform_device * mtx1_devs[] = { &mtx1_gpio_leds, &mtx1_wdt, - &mtx1_button + &mtx1_button, + &mtx1_mtd, }; static int __init mtx1_register_devices(void) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 17bc87a43ff4..d2fbc2964523 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -258,13 +258,6 @@ config MTD_ALCHEMY help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards -config MTD_MTX1 - tristate "4G Systems MTX-1 Flash device" - depends on MIPS_MTX1 && MTD_CFI - help - Flash memory access on 4G Systems MTX-1 Board. If you have one of - these boards and would like to use the flash chips on it, say 'Y'. - config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 957fb5f70f5e..c6ce8673dab2 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -65,5 +65,4 @@ obj-$(CONFIG_MTD_DMV182) += dmv182.o obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o -obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c deleted file mode 100644 index 2a8fde9b92f0..000000000000 --- a/drivers/mtd/maps/mtx-1_flash.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Flash memory access on 4G Systems MTX-1 boards - * - * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $ - * - * (C) 2005 Bruno Randolf - * (C) 2005 Joern Engel - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include - -static struct map_info mtx1_map = { - .name = "MTX-1 flash", - .bankwidth = 4, - .size = 0x2000000, - .phys = 0x1E000000, -}; - -static struct mtd_partition mtx1_partitions[] = { - { - .name = "filesystem", - .size = 0x01C00000, - .offset = 0, - },{ - .name = "yamon", - .size = 0x00100000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - },{ - .name = "kernel", - .size = 0x002c0000, - .offset = MTDPART_OFS_APPEND, - },{ - .name = "yamon env", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - } -}; - -static struct mtd_info *mtx1_mtd; - -int __init mtx1_mtd_init(void) -{ - int ret = -ENXIO; - - simple_map_init(&mtx1_map); - - mtx1_map.virt = ioremap(mtx1_map.phys, mtx1_map.size); - if (!mtx1_map.virt) - return -EIO; - - mtx1_mtd = do_map_probe("cfi_probe", &mtx1_map); - if (!mtx1_mtd) - goto err; - - mtx1_mtd->owner = THIS_MODULE; - - ret = add_mtd_partitions(mtx1_mtd, mtx1_partitions, - ARRAY_SIZE(mtx1_partitions)); - if (ret) - goto err; - - return 0; - -err: - iounmap(mtx1_map.virt); - return ret; -} - -static void __exit mtx1_mtd_cleanup(void) -{ - if (mtx1_mtd) { - del_mtd_partitions(mtx1_mtd); - map_destroy(mtx1_mtd); - } - if (mtx1_map.virt) - iounmap(mtx1_map.virt); -} - -module_init(mtx1_mtd_init); -module_exit(mtx1_mtd_cleanup); - -MODULE_AUTHOR("Bruno Randolf "); -MODULE_DESCRIPTION("MTX-1 flash map"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From daea34bc6f67cf3872d1b52ba5ccf249f3ceb176 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 May 2008 12:52:33 -0700 Subject: device create: mtd: convert device_create to device_create_drvdata device_create() is race-prone, so use the race-free device_create_drvdata() instead as device_create() is going away. Cc: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdchar.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 129d429cd2da..aef9f4b687c9 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -28,10 +28,13 @@ static void mtd_notify_add(struct mtd_info* mtd) if (!mtd) return; - device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), "mtd%d", mtd->index); + device_create_drvdata(mtd_class, NULL, + MKDEV(MTD_CHAR_MAJOR, mtd->index*2), + NULL, "mtd%d", mtd->index); - device_create(mtd_class, NULL, - MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), "mtd%dro", mtd->index); + device_create_drvdata(mtd_class, NULL, + MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), + NULL, "mtd%dro", mtd->index); } static void mtd_notify_remove(struct mtd_info* mtd) -- cgit v1.2.3-58-ga151 From eadcf0d704a46979c29984fa05f1fc413c775bcb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 2 Jul 2008 12:46:22 -0700 Subject: MTD: handle pci_name() being const This changes the MTD core to handle pci_name() now returning a constant string. Cc: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/devices/block2mtd.c | 8 +++++--- include/linux/mtd/map.h | 2 +- include/linux/mtd/mtd.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 519d942e7940..7b72a1b36115 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -241,6 +241,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) { struct block_device *bdev; struct block2mtd_dev *dev; + char *name; if (!devname) return NULL; @@ -279,12 +280,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) /* Setup the MTD structure */ /* make the name contain the block device in */ - dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname), + name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1, GFP_KERNEL); - if (!dev->mtd.name) + if (!name) goto devinit_err; - sprintf(dev->mtd.name, "block2mtd: %s", devname); + sprintf(name, "block2mtd: %s", devname); + dev->mtd.name = name; dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; dev->mtd.erasesize = erase_size; diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index a9fae032ba81..9c1d95491f8b 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -189,7 +189,7 @@ typedef union { */ struct map_info { - char *name; + const char *name; unsigned long size; resource_size_t phys; #define NO_XIP (-1UL) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 245f9098e171..8b5d49133ec6 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -121,7 +121,7 @@ struct mtd_info { u_int32_t oobavail; // Available OOB bytes per block // Kernel-only stuff starts here. - char *name; + const char *name; int index; /* ecc layout structure pointer - read only ! */ -- cgit v1.2.3-58-ga151 From 979c9296bdcfded58ebac41905c3397317df0355 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 14 May 2008 16:10:33 +0300 Subject: UBI: print error code Print error code if checking failed which is very useful to identify problems. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/vtbl.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index af36b12be278..3c4d68f2cfd4 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -127,7 +127,7 @@ static int vtbl_check(const struct ubi_device *ubi, const struct ubi_vtbl_record *vtbl) { int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len; - int upd_marker; + int upd_marker, err; uint32_t crc; const char *name; @@ -153,7 +153,7 @@ static int vtbl_check(const struct ubi_device *ubi, if (reserved_pebs == 0) { if (memcmp(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE)) { - dbg_err("bad empty record"); + err = 2; goto bad; } continue; @@ -161,56 +161,57 @@ static int vtbl_check(const struct ubi_device *ubi, if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 || name_len < 0) { - dbg_err("negative values"); + err = 3; goto bad; } if (alignment > ubi->leb_size || alignment == 0) { - dbg_err("bad alignment"); + err = 4; goto bad; } n = alignment % ubi->min_io_size; if (alignment != 1 && n) { - dbg_err("alignment is not multiple of min I/O unit"); + err = 5; goto bad; } n = ubi->leb_size % alignment; if (data_pad != n) { dbg_err("bad data_pad, has to be %d", n); + err = 6; goto bad; } if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) { - dbg_err("bad vol_type"); + err = 7; goto bad; } if (upd_marker != 0 && upd_marker != 1) { - dbg_err("bad upd_marker"); + err = 8; goto bad; } if (reserved_pebs > ubi->good_peb_count) { dbg_err("too large reserved_pebs, good PEBs %d", ubi->good_peb_count); + err = 9; goto bad; } if (name_len > UBI_VOL_NAME_MAX) { - dbg_err("too long volume name, max %d", - UBI_VOL_NAME_MAX); + err = 10; goto bad; } if (name[0] == '\0') { - dbg_err("NULL volume name"); + err = 11; goto bad; } if (name_len != strnlen(name, name_len + 1)) { - dbg_err("bad name_len"); + err = 12; goto bad; } } @@ -235,7 +236,7 @@ static int vtbl_check(const struct ubi_device *ubi, return 0; bad: - ubi_err("volume table check failed, record %d", i); + ubi_err("volume table check failed: record %d, error %d", i, err); ubi_dbg_dump_vtbl_record(&vtbl[i], i); return -EINVAL; } @@ -620,30 +621,32 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, static int check_sv(const struct ubi_volume *vol, const struct ubi_scan_volume *sv) { + int err; + if (sv->highest_lnum >= vol->reserved_pebs) { - dbg_err("bad highest_lnum"); + err = 1; goto bad; } if (sv->leb_count > vol->reserved_pebs) { - dbg_err("bad leb_count"); + err = 2; goto bad; } if (sv->vol_type != vol->vol_type) { - dbg_err("bad vol_type"); + err = 3; goto bad; } if (sv->used_ebs > vol->reserved_pebs) { - dbg_err("bad used_ebs"); + err = 4; goto bad; } if (sv->data_pad != vol->data_pad) { - dbg_err("bad data_pad"); + err = 5; goto bad; } return 0; bad: - ubi_err("bad scanning information"); + ubi_err("bad scanning information, error %d", err); ubi_dbg_dump_sv(sv); ubi_dbg_dump_vol_info(vol); return -EINVAL; -- cgit v1.2.3-58-ga151 From beeea636030622f6de67d15c61f5b311a03d188c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 20 May 2008 09:54:02 +0300 Subject: UBI: add a comment It is not clear why we schedule PEB for scrubbing in case of -EBADMSG. Elaborate. Requested-by: Kyungmin Park Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/vtbl.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 3c4d68f2cfd4..42a7815086b7 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -385,7 +385,16 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, ubi->vtbl_size); if (err == UBI_IO_BITFLIPS || err == -EBADMSG) - /* Scrub the PEB later */ + /* + * Scrub the PEB later. Note, -EBADMSG indicates an + * uncorrectable ECC error, but we have our own CRC and + * the data will be checked later. If the data is OK, + * the PEB will be scrubbed (because we set + * seb->scrub). If the data is not OK, the contents of + * the PEB will be recovered from the second copy, and + * seb->scrub will be cleared in + * 'ubi_scan_add_used()'. + */ seb->scrub = 1; else if (err) goto out_free; -- cgit v1.2.3-58-ga151 From a0fd1efd488092951f310fdb777b8a540cf84dcb Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Wed, 21 May 2008 14:34:56 +0300 Subject: UBI: fix buffer padding Instead of correctly pad the buffer wich we are writing to the eraseblock during update, we used weird construct: memset(buf + len, 0xFF, len - len); Fix this. Signed-off-by: Kyungmin Park Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/upd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index ddaa1a56cc69..6fa1ab3f2a70 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -237,10 +237,10 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, int err; if (vol->vol_type == UBI_DYNAMIC_VOLUME) { - len = ALIGN(len, ubi->min_io_size); - memset(buf + len, 0xFF, len - len); + int l = ALIGN(len, ubi->min_io_size); - len = ubi_calc_data_len(ubi, buf, len); + memset(buf + len, 0xFF, l - len); + len = ubi_calc_data_len(ubi, buf, l); if (len == 0) { dbg_msg("all %d bytes contain 0xFF - skip", len); return 0; -- cgit v1.2.3-58-ga151 From cadb40ccc16a26a738f1cbc963e35b21edd93e79 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 22 May 2008 10:32:18 +0900 Subject: UBI: avoid unnecessary division operations UBI already checks that @min io size is the power of 2 at io_init. It is save to use bit operations then. Signed-off-by: Kyungmin Park Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 8 ++++++-- drivers/mtd/ubi/cdev.c | 6 +++--- drivers/mtd/ubi/eba.c | 2 +- drivers/mtd/ubi/kapi.c | 6 +++--- drivers/mtd/ubi/misc.c | 2 +- drivers/mtd/ubi/vmt.c | 2 +- drivers/mtd/ubi/vtbl.c | 5 ++--- drivers/mtd/ubi/wl.c | 3 +-- 8 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 961416ac0616..ff4425de1527 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -530,7 +530,11 @@ static int io_init(struct ubi_device *ubi) ubi->min_io_size = ubi->mtd->writesize; ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; - /* Make sure minimal I/O unit is power of 2 */ + /* + * Make sure minimal I/O unit is power of 2. Note, there is no + * fundamental reason for this assumption. It is just an optimization + * which allows us to avoid costly division operations. + */ if (!is_power_of_2(ubi->min_io_size)) { ubi_err("min. I/O unit (%d) is not power of 2", ubi->min_io_size); @@ -581,7 +585,7 @@ static int io_init(struct ubi_device *ubi) if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE || ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE || ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE || - ubi->leb_start % ubi->min_io_size) { + ubi->leb_start & (ubi->min_io_size - 1)) { ubi_err("bad VID header (%d) or data offsets (%d)", ubi->vid_hdr_offset, ubi->leb_start); return -EINVAL; diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 89193ba9451e..0cdaf9fba7b0 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -295,7 +295,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, off = do_div(tmp, vol->usable_leb_size); lnum = tmp; - if (off % ubi->min_io_size) { + if (off & (ubi->min_io_size - 1)) { dbg_err("unaligned position"); return -EINVAL; } @@ -304,7 +304,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, count_save = count = vol->used_bytes - *offp; /* We can write only in fractions of the minimum I/O unit */ - if (count % ubi->min_io_size) { + if (count & (ubi->min_io_size - 1)) { dbg_err("unaligned write length"); return -EINVAL; } @@ -564,7 +564,7 @@ static int verify_mkvol_req(const struct ubi_device *ubi, if (req->alignment > ubi->leb_size) goto bad; - n = req->alignment % ubi->min_io_size; + n = req->alignment & (ubi->min_io_size - 1); if (req->alignment != 1 && n) goto bad; diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 7ce91ca742b1..37d778447943 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -752,7 +752,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, /* If this is the last LEB @len may be unaligned */ len = ALIGN(data_size, ubi->min_io_size); else - ubi_assert(len % ubi->min_io_size == 0); + ubi_assert(!(len & (ubi->min_io_size - 1))); vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); if (!vid_hdr) diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index a70d58823f8d..51508832566d 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -397,8 +397,8 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, return -EROFS; if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 || - offset + len > vol->usable_leb_size || offset % ubi->min_io_size || - len % ubi->min_io_size) + offset + len > vol->usable_leb_size || + offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1)) return -EINVAL; if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && @@ -447,7 +447,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, return -EROFS; if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 || - len > vol->usable_leb_size || len % ubi->min_io_size) + len > vol->usable_leb_size || len & (ubi->min_io_size - 1)) return -EINVAL; if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c index 93e052812012..22ad31402945 100644 --- a/drivers/mtd/ubi/misc.c +++ b/drivers/mtd/ubi/misc.c @@ -37,7 +37,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, { int i; - ubi_assert(length % ubi->min_io_size == 0); + ubi_assert(!(length & (ubi->min_io_size - 1))); for (i = length - 1; i >= 0; i--) if (((const uint8_t *)buf)[i] != 0xFF) diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 5be58d85c639..7402025ded94 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -727,7 +727,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) goto fail; } - n = vol->alignment % ubi->min_io_size; + n = vol->alignment & (ubi->min_io_size - 1); if (vol->alignment != 1 && n) { ubi_err("alignment is not multiple of min I/O unit"); goto fail; diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 42a7815086b7..d9af11a8682b 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -170,7 +170,7 @@ static int vtbl_check(const struct ubi_device *ubi, goto bad; } - n = alignment % ubi->min_io_size; + n = alignment & (ubi->min_io_size - 1); if (alignment != 1 && n) { err = 5; goto bad; @@ -684,14 +684,13 @@ static int check_scanning_info(const struct ubi_device *ubi, return -EINVAL; } - if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT&& + if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT && si->highest_vol_id < UBI_INTERNAL_VOL_START) { ubi_err("too large volume ID %d found by scanning", si->highest_vol_id); return -EINVAL; } - for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { cond_resched(); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index a471a491f0ab..cc8fe2934d2b 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1368,7 +1368,7 @@ int ubi_thread(void *u) int err; if (kthread_should_stop()) - goto out; + break; if (try_to_freeze()) continue; @@ -1403,7 +1403,6 @@ int ubi_thread(void *u) cond_resched(); } -out: dbg_wl("background thread \"%s\" is killed", ubi->bgt_name); return 0; } -- cgit v1.2.3-58-ga151 From abc5e92262d87f9c5c628492bffc55f81c7dcb80 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Jun 2008 16:48:12 +0300 Subject: UBI: fix memory leak ubi_free_volume() function sets ubi->volumes[] to NULL, so ubi_eba_close() is useless, it does not free what has to be freed. So zap it and free vol->eba_tbl at the volume release function. Pointed-out-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 2 -- drivers/mtd/ubi/eba.c | 17 ----------------- drivers/mtd/ubi/ubi.h | 1 - drivers/mtd/ubi/vmt.c | 18 +++++++++--------- 4 files changed, 9 insertions(+), 29 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index ff4425de1527..7b42b4d05b3a 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -840,7 +840,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) out_uif: uif_close(ubi); out_detach: - ubi_eba_close(ubi); ubi_wl_close(ubi); vfree(ubi->vtbl); out_free: @@ -903,7 +902,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) kthread_stop(ubi->bgt_thread); uif_close(ubi); - ubi_eba_close(ubi); ubi_wl_close(ubi); vfree(ubi->vtbl); put_mtd_device(ubi->mtd); diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 37d778447943..623d25f4855f 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -1233,20 +1233,3 @@ out_free: } return err; } - -/** - * ubi_eba_close - close EBA unit. - * @ubi: UBI device description object - */ -void ubi_eba_close(const struct ubi_device *ubi) -{ - int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; - - dbg_eba("close EBA unit"); - - for (i = 0; i < num_volumes; i++) { - if (!ubi->volumes[i]) - continue; - kfree(ubi->volumes[i]->eba_tbl); - } -} diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 67dcbd11c15c..940f6b7deec3 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -477,7 +477,6 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, struct ubi_vid_hdr *vid_hdr); int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); -void ubi_eba_close(const struct ubi_device *ubi); /* wl.c */ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 7402025ded94..367b04176e0a 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -127,6 +127,7 @@ static void vol_release(struct device *dev) { struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); + kfree(vol->eba_tbl); kfree(vol); } @@ -201,7 +202,7 @@ static void volume_sysfs_close(struct ubi_volume *vol) */ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) { - int i, err, vol_id = req->vol_id, dont_free = 0; + int i, err, vol_id = req->vol_id, do_free = 1; struct ubi_volume *vol; struct ubi_vtbl_record vtbl_rec; uint64_t bytes; @@ -365,14 +366,14 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) out_sysfs: /* - * We have registered our device, we should not free the volume* + * We have registered our device, we should not free the volume * description object in this function in case of an error - it is * freed by the release function. * * Get device reference to prevent the release function from being * called just after sysfs has been closed. */ - dont_free = 1; + do_free = 0; get_device(&vol->dev); volume_sysfs_close(vol); out_gluebi: @@ -382,17 +383,18 @@ out_gluebi: out_cdev: cdev_del(&vol->cdev); out_mapping: - kfree(vol->eba_tbl); + if (do_free) + kfree(vol->eba_tbl); out_acc: spin_lock(&ubi->volumes_lock); ubi->rsvd_pebs -= vol->reserved_pebs; ubi->avail_pebs += vol->reserved_pebs; out_unlock: spin_unlock(&ubi->volumes_lock); - if (dont_free) - put_device(&vol->dev); - else + if (do_free) kfree(vol); + else + put_device(&vol->dev); ubi_err("cannot create volume %d, error %d", vol_id, err); return err; } @@ -445,8 +447,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) goto out_err; } - kfree(vol->eba_tbl); - vol->eba_tbl = NULL; cdev_del(&vol->cdev); volume_sysfs_close(vol); -- cgit v1.2.3-58-ga151 From 505d1caa79cd61a70615e9a7eae2eab85e797a83 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Jun 2008 17:00:35 +0300 Subject: UBI: do not forget to free internal volumes UBI forgets to free internal volumes when detaching MTD device. Fix this. Pointed-out-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 7b42b4d05b3a..33205e4c1f5b 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -422,6 +422,10 @@ out_unreg: /** * uif_close - close user interfaces for an UBI device. * @ubi: UBI device description object + * + * Note, since this function un-registers UBI volume device objects (@vol->dev), + * the memory allocated voe the volumes is freed as well (in the release + * function). */ static void uif_close(struct ubi_device *ubi) { @@ -431,6 +435,21 @@ static void uif_close(struct ubi_device *ubi) unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); } +/** + * free_internal_volumes - free internal volumes. + * @ubi: UBI device description object + */ +static void free_internal_volumes(struct ubi_device *ubi) +{ + int i; + + for (i = ubi->vtbl_slots; + i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { + kfree(ubi->volumes[i]->eba_tbl); + kfree(ubi->volumes[i]); + } +} + /** * attach_by_scanning - attach an MTD device using scanning method. * @ubi: UBI device descriptor @@ -475,6 +494,7 @@ static int attach_by_scanning(struct ubi_device *ubi) out_wl: ubi_wl_close(ubi); out_vtbl: + free_internal_volumes(ubi); vfree(ubi->vtbl); out_si: ubi_scan_destroy_si(si); @@ -650,7 +670,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) /* * Clear the auto-resize flag in the volume in-memory copy of the - * volume table, and 'ubi_resize_volume()' will propogate this change + * volume table, and 'ubi_resize_volume()' will propagate this change * to the flash. */ ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; @@ -659,7 +679,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) struct ubi_vtbl_record vtbl_rec; /* - * No avalilable PEBs to re-size the volume, clear the flag on + * No available PEBs to re-size the volume, clear the flag on * flash and exit. */ memcpy(&vtbl_rec, &ubi->vtbl[vol_id], @@ -692,7 +712,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) * * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in - * which case this function finds a vacant device nubert and assings it + * which case this function finds a vacant device number and assigns it * automatically. Returns the new UBI device number in case of success and a * negative error code in case of failure. * @@ -841,6 +861,7 @@ out_uif: uif_close(ubi); out_detach: ubi_wl_close(ubi); + free_internal_volumes(ubi); vfree(ubi->vtbl); out_free: vfree(ubi->peb_buf1); @@ -903,6 +924,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) uif_close(ubi); ubi_wl_close(ubi); + free_internal_volumes(ubi); vfree(ubi->vtbl); put_mtd_device(ubi->mtd); vfree(ubi->peb_buf1); -- cgit v1.2.3-58-ga151 From 472018f73e7308a7f29b753ee8c742b6f45f103f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Jun 2008 17:58:37 +0300 Subject: UBI: fix memory leak on error path Normally UBI volumes are freed in the release function of the struct device object. However, on error path they may have to be freed before the struct device objects have been initialized. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 33205e4c1f5b..a5b19944eca8 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -354,16 +354,35 @@ static void kill_volumes(struct ubi_device *ubi) ubi_free_volume(ubi, ubi->volumes[i]); } +/** + * free_user_volumes - free all user volumes. + * @ubi: UBI device description object + * + * Normally the volumes are freed at the release function of the volume device + * objects. However, on error paths the volumes have to be freed before the + * device objects have been initialized. + */ +static void free_user_volumes(struct ubi_device *ubi) +{ + int i; + + for (i = 0; i < ubi->vtbl_slots; i++) + if (ubi->volumes[i]) { + kfree(ubi->volumes[i]->eba_tbl); + kfree(ubi->volumes[i]); + } +} + /** * uif_init - initialize user interfaces for an UBI device. * @ubi: UBI device description object * * This function returns zero in case of success and a negative error code in - * case of failure. + * case of failure. Note, this function destroys all volumes if it failes. */ static int uif_init(struct ubi_device *ubi) { - int i, err; + int i, err, do_free = 0; dev_t dev; sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); @@ -410,10 +429,13 @@ static int uif_init(struct ubi_device *ubi) out_volumes: kill_volumes(ubi); + do_free = 0; out_sysfs: ubi_sysfs_close(ubi); cdev_del(&ubi->cdev); out_unreg: + if (do_free) + free_user_volumes(ubi); unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); return err; @@ -722,7 +744,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) { struct ubi_device *ubi; - int i, err; + int i, err, do_free = 1; /* * Check if we already have the same MTD device attached. @@ -822,7 +844,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) err = uif_init(ubi); if (err) - goto out_detach; + goto out_nofree; ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); if (IS_ERR(ubi->bgt_thread)) { @@ -859,8 +881,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) out_uif: uif_close(ubi); +out_nofree: + do_free = 0; out_detach: ubi_wl_close(ubi); + if (do_free) + free_user_volumes(ubi); free_internal_volumes(ubi); vfree(ubi->vtbl); out_free: -- cgit v1.2.3-58-ga151 From 23add7455c42eef63f8719bd268328047d4aed69 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 16 Jun 2008 13:35:23 +0300 Subject: UBI: fix LEB locking leb_read_unlock() may be called simultaniously by several tasks. The would race at the following code: up_read(&le->mutex); if (free) kfree(le); And it is possible that one task frees 'le' before the other tasks do 'up_read()'. Fix this by doing up_read and free inside the 'ubi->ltree' lock. Below it the oops we had because of this: BUG: spinlock bad magic on CPU#0, integck/7504 BUG: unable to handle kernel paging request at 6b6b6c4f IP: [] spin_bug+0x5c/0xdb *pde = 00000000 Oops: 0000 [#1] PREEMPT SMP Modules linked in: ubifs ubi nandsim nand nand_ids nand_ecc video output Pid: 7504, comm: integck Not tainted (2.6.26-rc3ubifs26 #8) EIP: 0060:[] EFLAGS: 00010002 CPU: 0 EIP is at spin_bug+0x5c/0xdb EAX: 00000032 EBX: 6b6b6b6b ECX: 6b6b6b6b EDX: f7f7ce30 ESI: f76491dc EDI: c044f51f EBP: e8a736cc ESP: e8a736a8 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Process integck (pid: 7504, ti=e8a72000 task=f7f7ce30 task.ti=e8a72000) Stack: c044f754 c044f51f 00000000 f7f7d024 00001d50 00000001 f76491dc 00000296 f6df50e0 e8a736d8 c02112f0 f76491dc e8a736e8 c039157a f7d9e830 f76491d8 e8a7370c c020b975 f76491dc 00000296 f76491f8 00000000 f76491d8 00000000 Call Trace: [] ? _raw_spin_unlock+0x50/0x7c [] ? _spin_unlock_irqrestore+0x20/0x58 [] ? rwsem_wake+0x4b/0x122 [] ? call_rwsem_wake+0xa/0xc [] ? up_read+0x28/0x31 [] ? leb_read_unlock+0x73/0x7b [ubi] [] ? ubi_eba_read_leb+0x195/0x2b0 [ubi] [] ? ubi_leb_read+0xaf/0xf8 [ubi] Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/eba.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 623d25f4855f..8dc488fc0cdf 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -223,22 +223,18 @@ static int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum) */ static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) { - int free = 0; struct ubi_ltree_entry *le; spin_lock(&ubi->ltree_lock); le = ltree_lookup(ubi, vol_id, lnum); le->users -= 1; ubi_assert(le->users >= 0); + up_read(&le->mutex); if (le->users == 0) { rb_erase(&le->rb, &ubi->ltree); - free = 1; + kfree(le); } spin_unlock(&ubi->ltree_lock); - - up_read(&le->mutex); - if (free) - kfree(le); } /** @@ -274,7 +270,6 @@ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum) */ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) { - int free; struct ubi_ltree_entry *le; le = ltree_add_entry(ubi, vol_id, lnum); @@ -289,12 +284,9 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) ubi_assert(le->users >= 0); if (le->users == 0) { rb_erase(&le->rb, &ubi->ltree); - free = 1; - } else - free = 0; - spin_unlock(&ubi->ltree_lock); - if (free) kfree(le); + } + spin_unlock(&ubi->ltree_lock); return 1; } @@ -307,23 +299,18 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) */ static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) { - int free; struct ubi_ltree_entry *le; spin_lock(&ubi->ltree_lock); le = ltree_lookup(ubi, vol_id, lnum); le->users -= 1; ubi_assert(le->users >= 0); + up_write(&le->mutex); if (le->users == 0) { rb_erase(&le->rb, &ubi->ltree); - free = 1; - } else - free = 0; - spin_unlock(&ubi->ltree_lock); - - up_write(&le->mutex); - if (free) kfree(le); + } + spin_unlock(&ubi->ltree_lock); } /** -- cgit v1.2.3-58-ga151 From 73789a3d9fd8e500e121c1d4a5a2b16dd748ab5f Mon Sep 17 00:00:00 2001 From: Bruce Leonard Date: Thu, 3 Jul 2008 10:35:49 +0300 Subject: UBI: fix 64-bit calculations Signed-off-by: Bruce Leonard Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/cdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 0cdaf9fba7b0..3e3449ec07f0 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -437,7 +437,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, break; } - rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad); + rsvd_bytes = (long long)vol->reserved_pebs * + ubi->leb_size-vol->data_pad; if (bytes < 0 || bytes > rsvd_bytes) { err = -EINVAL; break; -- cgit v1.2.3-58-ga151 From a5bf6190417cbbf80443a9f71c65b653e13e9982 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 10 Jul 2008 18:38:33 +0300 Subject: UBI: add ubi_sync() interface To flush MTD device caches. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/kapi.c | 24 ++++++++++++++++++++++++ include/linux/mtd/ubi.h | 1 + 2 files changed, 25 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 51508832566d..e65c8e0bcd5d 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -632,3 +632,27 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum) return vol->eba_tbl[lnum] >= 0; } EXPORT_SYMBOL_GPL(ubi_is_mapped); + +/** + * ubi_sync - synchronize UBI device buffers. + * @ubi_num: UBI device to synchronize + * + * The underlying MTD device may cache data in hardware or in software. This + * function ensures the caches are flushed. Returns zero in case of success and + * a negative error code in case of failure. + */ +int ubi_sync(int ubi_num) +{ + struct ubi_device *ubi; + + ubi = ubi_get_device(ubi_num); + if (!ubi) + return -ENODEV; + + if (ubi->mtd->sync) + ubi->mtd->sync(ubi->mtd); + + ubi_put_device(ubi); + return 0; +} +EXPORT_SYMBOL_GPL(ubi_sync); diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h index f71201d0f3e7..83302bbbddb4 100644 --- a/include/linux/mtd/ubi.h +++ b/include/linux/mtd/ubi.h @@ -152,6 +152,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum); int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum); int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype); int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); +int ubi_sync(int ubi_num); /* * This function is the same as the 'ubi_leb_read()' function, but it does not -- cgit v1.2.3-58-ga151 From a6ea440769e11c46828cddd20f91ab57261701d5 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 13 Jul 2008 21:46:24 +0300 Subject: UBI: improve mkvol request validation Check that volume name is not shorter than 'name_len'. No need to copy the trailing zero byte because whole array was zeroed earlier. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/cdev.c | 7 +++++-- drivers/mtd/ubi/vmt.c | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 3e3449ec07f0..4fb84e3e6502 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -574,6 +574,10 @@ static int verify_mkvol_req(const struct ubi_device *ubi, goto bad; } + n = strnlen(req->name, req->name_len + 1); + if (n != req->name_len) + goto bad; + return 0; bad: @@ -629,12 +633,11 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, break; } + req.name[req.name_len] = '\0'; err = verify_mkvol_req(ubi, &req); if (err) break; - req.name[req.name_len] = '\0'; - mutex_lock(&ubi->volumes_mutex); err = ubi_create_volume(ubi, &req); mutex_unlock(&ubi->volumes_mutex); diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 367b04176e0a..bfa7c5d2e064 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -275,7 +275,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) vol->data_pad = ubi->leb_size % vol->alignment; vol->vol_type = req->vol_type; vol->name_len = req->name_len; - memcpy(vol->name, req->name, vol->name_len + 1); + memcpy(vol->name, req->name, vol->name_len); vol->ubi = ubi; /* @@ -350,7 +350,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) vtbl_rec.vol_type = UBI_VID_DYNAMIC; else vtbl_rec.vol_type = UBI_VID_STATIC; - memcpy(vtbl_rec.name, vol->name, vol->name_len + 1); + memcpy(vtbl_rec.name, vol->name, vol->name_len); err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); if (err) -- cgit v1.2.3-58-ga151 From bb84c1a199558962edf4b4aeb4480fb09aa09b91 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 14 Jul 2008 12:57:27 +0300 Subject: UBI: fix error message The ubi_err() macro will add \n. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/gluebi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index e909b390069a..ae76ab638b2f 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c @@ -299,7 +299,7 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol) mtd->size = vol->used_bytes; if (add_mtd_device(mtd)) { - ubi_err("cannot not add MTD device\n"); + ubi_err("cannot not add MTD device"); kfree(mtd->name); return -ENFILE; } -- cgit v1.2.3-58-ga151 From 85c6e6e28259e9b58b8984db536c45bc3161f40c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 16 Jul 2008 10:25:56 +0300 Subject: UBI: amend commentaries Hch asked not to use "unit" for sub-systems, let it be so. Also some other commentaries modifications. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 2 +- drivers/mtd/ubi/debug.h | 6 +-- drivers/mtd/ubi/eba.c | 22 +++++------ drivers/mtd/ubi/io.c | 22 +++++------ drivers/mtd/ubi/scan.c | 28 +++++++------- drivers/mtd/ubi/scan.h | 19 +++++---- drivers/mtd/ubi/ubi-media.h | 23 +++++------ drivers/mtd/ubi/ubi.h | 37 +++++++++--------- drivers/mtd/ubi/wl.c | 94 ++++++++++++++++++++++----------------------- include/linux/mtd/ubi.h | 4 +- 10 files changed, 129 insertions(+), 128 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index a5b19944eca8..27271fe32e02 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -524,7 +524,7 @@ out_si: } /** - * io_init - initialize I/O unit for a given UBI device. + * io_init - initialize I/O sub-system for a given UBI device. * @ubi: UBI device description object * * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 8ea99d8c9e1f..7d8d77c31dfe 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -76,21 +76,21 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); #endif /* CONFIG_MTD_UBI_DEBUG_MSG */ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA -/* Messages from the eraseblock association unit */ +/* Messages from the eraseblock association sub-system */ #define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) #else #define dbg_eba(fmt, ...) ({}) #endif #ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL -/* Messages from the wear-leveling unit */ +/* Messages from the wear-leveling sub-system */ #define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) #else #define dbg_wl(fmt, ...) ({}) #endif #ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO -/* Messages from the input/output unit */ +/* Messages from the input/output sub-system */ #define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) #else #define dbg_io(fmt, ...) ({}) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 8dc488fc0cdf..613cd1e51648 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -19,20 +19,20 @@ */ /* - * The UBI Eraseblock Association (EBA) unit. + * The UBI Eraseblock Association (EBA) sub-system. * - * This unit is responsible for I/O to/from logical eraseblock. + * This sub-system is responsible for I/O to/from logical eraseblock. * * Although in this implementation the EBA table is fully kept and managed in * RAM, which assumes poor scalability, it might be (partially) maintained on * flash in future implementations. * - * The EBA unit implements per-logical eraseblock locking. Before accessing a - * logical eraseblock it is locked for reading or writing. The per-logical - * eraseblock locking is implemented by means of the lock tree. The lock tree - * is an RB-tree which refers all the currently locked logical eraseblocks. The - * lock tree elements are &struct ubi_ltree_entry objects. They are indexed by - * (@vol_id, @lnum) pairs. + * The EBA sub-system implements per-logical eraseblock locking. Before + * accessing a logical eraseblock it is locked for reading or writing. The + * per-logical eraseblock locking is implemented by means of the lock tree. The + * lock tree is an RB-tree which refers all the currently locked logical + * eraseblocks. The lock tree elements are &struct ubi_ltree_entry objects. + * They are indexed by (@vol_id, @lnum) pairs. * * EBA also maintains the global sequence counter which is incremented each * time a logical eraseblock is mapped to a physical eraseblock and it is @@ -1128,7 +1128,7 @@ out_unlock_leb: } /** - * ubi_eba_init_scan - initialize the EBA unit using scanning information. + * ubi_eba_init_scan - initialize the EBA sub-system using scanning information. * @ubi: UBI device description object * @si: scanning information * @@ -1143,7 +1143,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) struct ubi_scan_leb *seb; struct rb_node *rb; - dbg_eba("initialize EBA unit"); + dbg_eba("initialize EBA sub-system"); spin_lock_init(&ubi->ltree_lock); mutex_init(&ubi->alc_mutex); @@ -1209,7 +1209,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) ubi->rsvd_pebs += ubi->beb_rsvd_pebs; } - dbg_eba("EBA unit is initialized"); + dbg_eba("EBA sub-system is initialized"); return 0; out_free: diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 4ac11df7b048..561e7b2f96cb 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -20,15 +20,15 @@ */ /* - * UBI input/output unit. + * UBI input/output sub-system. * - * This unit provides a uniform way to work with all kinds of the underlying - * MTD devices. It also implements handy functions for reading and writing UBI - * headers. + * This sub-system provides a uniform way to work with all kinds of the + * underlying MTD devices. It also implements handy functions for reading and + * writing UBI headers. * * We are trying to have a paranoid mindset and not to trust to what we read - * from the flash media in order to be more secure and robust. So this unit - * validates every single header it reads from the flash media. + * from the flash media in order to be more secure and robust. So this + * sub-system validates every single header it reads from the flash media. * * Some words about how the eraseblock headers are stored. * @@ -79,11 +79,11 @@ * 512-byte chunks, we have to allocate one more buffer and copy our VID header * to offset 448 of this buffer. * - * The I/O unit does the following trick in order to avoid this extra copy. - * It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID header - * and returns a pointer to offset @ubi->vid_hdr_shift of this buffer. When the - * VID header is being written out, it shifts the VID header pointer back and - * writes the whole sub-page. + * The I/O sub-system does the following trick in order to avoid this extra + * copy. It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID + * header and returns a pointer to offset @ubi->vid_hdr_shift of this buffer. + * When the VID header is being written out, it shifts the VID header pointer + * back and writes the whole sub-page. */ #include diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 96d410e106ab..892c2ba49777 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -19,9 +19,9 @@ */ /* - * UBI scanning unit. + * UBI scanning sub-system. * - * This unit is responsible for scanning the flash media, checking UBI + * This sub-system is responsible for scanning the flash media, checking UBI * headers and providing complete information about the UBI flash image. * * The scanning information is represented by a &struct ubi_scan_info' object. @@ -103,7 +103,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, * non-zero if an inconsistency was found and zero if not. * * Note, UBI does sanity check of everything it reads from the flash media. - * Most of the checks are done in the I/O unit. Here we check that the + * Most of the checks are done in the I/O sub-system. Here we check that the * information in the VID header is consistent to the information in other VID * headers of the same volume. */ @@ -256,8 +256,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, * that versions that are close to %0xFFFFFFFF are less then * versions that are close to %0. * - * The UBI WL unit guarantees that the number of pending tasks - * is not greater then %0x7FFFFFFF. So, if the difference + * The UBI WL sub-system guarantees that the number of pending + * tasks is not greater then %0x7FFFFFFF. So, if the difference * between any two versions is greater or equivalent to * %0x7FFFFFFF, there was an overflow and the logical * eraseblock with lower version is actually newer then the one @@ -645,9 +645,9 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv) * * This function erases physical eraseblock 'pnum', and writes the erase * counter header to it. This function should only be used on UBI device - * initialization stages, when the EBA unit had not been yet initialized. This - * function returns zero in case of success and a negative error code in case - * of failure. + * initialization stages, when the EBA sub-system had not been yet initialized. + * This function returns zero in case of success and a negative error code in + * case of failure. */ int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, int pnum, int ec) @@ -687,9 +687,10 @@ out_free: * @si: scanning information * * This function returns a free physical eraseblock. It is supposed to be - * called on the UBI initialization stages when the wear-leveling unit is not - * initialized yet. This function picks a physical eraseblocks from one of the - * lists, writes the EC header if it is needed, and removes it from the list. + * called on the UBI initialization stages when the wear-leveling sub-system is + * not initialized yet. This function picks a physical eraseblocks from one of + * the lists, writes the EC header if it is needed, and removes it from the + * list. * * This function returns scanning physical eraseblock information in case of * success and an error code in case of failure. @@ -764,8 +765,9 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum return err; else if (err) { /* - * FIXME: this is actually duty of the I/O unit to initialize - * this, but MTD does not provide enough information. + * FIXME: this is actually duty of the I/O sub-system to + * initialize this, but MTD does not provide enough + * information. */ si->bad_peb_count += 1; return 0; diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 966b9b682a42..4e2e3cc0becd 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -59,16 +59,16 @@ struct ubi_scan_leb { * @leb_count: number of logical eraseblocks in this volume * @vol_type: volume type * @used_ebs: number of used logical eraseblocks in this volume (only for - * static volumes) + * static volumes) * @last_data_size: amount of data in the last logical eraseblock of this - * volume (always equivalent to the usable logical eraseblock size in case of - * dynamic volumes) + * volume (always equivalent to the usable logical eraseblock + * size in case of dynamic volumes) * @data_pad: how many bytes at the end of logical eraseblocks of this volume - * are not used (due to volume alignment) + * are not used (due to volume alignment) * @compat: compatibility flags of this volume * @rb: link in the volume RB-tree * @root: root of the RB-tree containing all the eraseblock belonging to this - * volume (&struct ubi_scan_leb objects) + * volume (&struct ubi_scan_leb objects) * * One object of this type is allocated for each volume during scanning. */ @@ -92,8 +92,8 @@ struct ubi_scan_volume { * @free: list of free physical eraseblocks * @erase: list of physical eraseblocks which have to be erased * @alien: list of physical eraseblocks which should not be used by UBI (e.g., + * those belonging to "preserve"-compatible internal volumes) * @bad_peb_count: count of bad physical eraseblocks - * those belonging to "preserve"-compatible internal volumes) * @vols_found: number of volumes found during scanning * @highest_vol_id: highest volume ID * @alien_peb_count: count of physical eraseblocks in the @alien list @@ -106,8 +106,8 @@ struct ubi_scan_volume { * @ec_count: a temporary variable used when calculating @mean_ec * * This data structure contains the result of scanning and may be used by other - * UBI units to build final UBI data structures, further error-recovery and so - * on. + * UBI sub-systems to build final UBI data structures, further error-recovery + * and so on. */ struct ubi_scan_info { struct rb_root volumes; @@ -132,8 +132,7 @@ struct ubi_device; struct ubi_vid_hdr; /* - * ubi_scan_move_to_list - move a physical eraseblock from the volume tree to a - * list. + * ubi_scan_move_to_list - move a PEB from the volume tree to a list. * * @sv: volume scanning information * @seb: scanning eraseblock infprmation diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index c3185d9fd048..26bb7af9787a 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h @@ -98,10 +98,11 @@ enum { * Compatibility constants used by internal volumes. * * @UBI_COMPAT_DELETE: delete this internal volume before anything is written - * to the flash + * to the flash * @UBI_COMPAT_RO: attach this device in read-only mode * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its - * physical eraseblocks, don't allow the wear-leveling unit to move them + * physical eraseblocks, don't allow the wear-leveling + * sub-system to move them * @UBI_COMPAT_REJECT: reject this UBI image */ enum { @@ -123,7 +124,7 @@ enum { * struct ubi_ec_hdr - UBI erase counter header. * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC) * @version: version of UBI implementation which is supposed to accept this - * UBI image + * UBI image * @padding1: reserved for future, zeroes * @ec: the erase counter * @vid_hdr_offset: where the VID header starts @@ -159,20 +160,20 @@ struct ubi_ec_hdr { * struct ubi_vid_hdr - on-flash UBI volume identifier header. * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC) * @version: UBI implementation version which is supposed to accept this UBI - * image (%UBI_VERSION) + * image (%UBI_VERSION) * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) * @copy_flag: if this logical eraseblock was copied from another physical - * eraseblock (for wear-leveling reasons) + * eraseblock (for wear-leveling reasons) * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, - * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) + * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) * @vol_id: ID of this volume * @lnum: logical eraseblock number * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be - * removed, kept only for not breaking older UBI users) + * removed, kept only for not breaking older UBI users) * @data_size: how many bytes of data this logical eraseblock contains * @used_ebs: total number of used logical eraseblocks in this volume * @data_pad: how many bytes at the end of this physical eraseblock are not - * used + * used * @data_crc: CRC checksum of the data stored in this logical eraseblock * @padding1: reserved for future, zeroes * @sqnum: sequence number @@ -248,9 +249,9 @@ struct ubi_ec_hdr { * The @data_crc field contains the CRC checksum of the contents of the logical * eraseblock if this is a static volume. In case of dynamic volumes, it does * not contain the CRC checksum as a rule. The only exception is when the - * data of the physical eraseblock was moved by the wear-leveling unit, then - * the wear-leveling unit calculates the data CRC and stores it in the - * @data_crc field. And of course, the @copy_flag is %in this case. + * data of the physical eraseblock was moved by the wear-leveling sub-system, + * then the wear-leveling sub-system calculates the data CRC and stores it in + * the @data_crc field. And of course, the @copy_flag is %in this case. * * The @data_size field is used only for static volumes because UBI has to know * how many bytes of data are stored in this eraseblock. For dynamic volumes, diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 940f6b7deec3..1fc32c863b78 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -74,15 +74,15 @@ #define UBI_IO_RETRIES 3 /* - * Error codes returned by the I/O unit. + * Error codes returned by the I/O sub-system. * * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only - * 0xFF bytes + * %0xFF bytes * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a - * valid erase counter header, and the rest are %0xFF bytes + * valid erase counter header, and the rest are %0xFF bytes * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC) * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or - * CRC) + * CRC) * UBI_IO_BITFLIPS: bit-flips were detected and corrected */ enum { @@ -99,9 +99,9 @@ enum { * @ec: erase counter * @pnum: physical eraseblock number * - * This data structure is used in the WL unit. Each physical eraseblock has a - * corresponding &struct wl_entry object which may be kept in different - * RB-trees. See WL unit for details. + * This data structure is used in the WL sub-system. Each physical eraseblock + * has a corresponding &struct wl_entry object which may be kept in different + * RB-trees. See WL sub-system for details. */ struct ubi_wl_entry { struct rb_node rb; @@ -118,10 +118,10 @@ struct ubi_wl_entry { * @mutex: read/write mutex to implement read/write access serialization to * the (@vol_id, @lnum) logical eraseblock * - * This data structure is used in the EBA unit to implement per-LEB locking. - * When a logical eraseblock is being locked - corresponding + * This data structure is used in the EBA sub-system to implement per-LEB + * locking. When a logical eraseblock is being locked - corresponding * &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree). - * See EBA unit for details. + * See EBA sub-system for details. */ struct ubi_ltree_entry { struct rb_node rb; @@ -225,7 +225,7 @@ struct ubi_volume { #ifdef CONFIG_MTD_UBI_GLUEBI /* * Gluebi-related stuff may be compiled out. - * TODO: this should not be built into UBI but should be a separate + * Note: this should not be built into UBI but should be a separate * ubimtd driver which works on top of UBI and emulates MTD devices. */ struct ubi_volume_desc *gluebi_desc; @@ -235,8 +235,7 @@ struct ubi_volume { }; /** - * struct ubi_volume_desc - descriptor of the UBI volume returned when it is - * opened. + * struct ubi_volume_desc - UBI volume descriptor returned when it is opened. * @vol: reference to the corresponding volume description object * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE) */ @@ -316,11 +315,11 @@ struct ubi_wl_entry; * @ro_mode: if the UBI device is in read-only mode * @leb_size: logical eraseblock size * @leb_start: starting offset of logical eraseblocks within physical - * eraseblocks + * eraseblocks * @ec_hdr_alsize: size of the EC header aligned to @hdrs_min_io_size * @vid_hdr_alsize: size of the VID header aligned to @hdrs_min_io_size * @vid_hdr_offset: starting offset of the volume identifier header (might be - * unaligned) + * unaligned) * @vid_hdr_aloffset: starting offset of the VID header aligned to * @hdrs_min_io_size * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset @@ -356,16 +355,16 @@ struct ubi_device { struct mutex volumes_mutex; int max_ec; - /* TODO: mean_ec is not updated run-time, fix */ + /* Note, mean_ec is not updated run-time - should be fixed */ int mean_ec; - /* EBA unit's stuff */ + /* EBA sub-system's stuff */ unsigned long long global_sqnum; spinlock_t ltree_lock; struct rb_root ltree; struct mutex alc_mutex; - /* Wear-leveling unit's stuff */ + /* Wear-leveling sub-system's stuff */ struct rb_root used; struct rb_root free; struct rb_root scrub; @@ -388,7 +387,7 @@ struct ubi_device { int thread_enabled; char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2]; - /* I/O unit's stuff */ + /* I/O sub-system's stuff */ long long flash_size; int peb_count; int peb_size; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index cc8fe2934d2b..761952ba125b 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -19,22 +19,22 @@ */ /* - * UBI wear-leveling unit. + * UBI wear-leveling sub-system. * - * This unit is responsible for wear-leveling. It works in terms of physical - * eraseblocks and erase counters and knows nothing about logical eraseblocks, - * volumes, etc. From this unit's perspective all physical eraseblocks are of - * two types - used and free. Used physical eraseblocks are those that were - * "get" by the 'ubi_wl_get_peb()' function, and free physical eraseblocks are - * those that were put by the 'ubi_wl_put_peb()' function. + * This sub-system is responsible for wear-leveling. It works in terms of + * physical* eraseblocks and erase counters and knows nothing about logical + * eraseblocks, volumes, etc. From this sub-system's perspective all physical + * eraseblocks are of two types - used and free. Used physical eraseblocks are + * those that were "get" by the 'ubi_wl_get_peb()' function, and free physical + * eraseblocks are those that were put by the 'ubi_wl_put_peb()' function. * * Physical eraseblocks returned by 'ubi_wl_get_peb()' have only erase counter - * header. The rest of the physical eraseblock contains only 0xFF bytes. + * header. The rest of the physical eraseblock contains only %0xFF bytes. * - * When physical eraseblocks are returned to the WL unit by means of the + * When physical eraseblocks are returned to the WL sub-system by means of the * 'ubi_wl_put_peb()' function, they are scheduled for erasure. The erasure is * done asynchronously in context of the per-UBI device background thread, - * which is also managed by the WL unit. + * which is also managed by the WL sub-system. * * The wear-leveling is ensured by means of moving the contents of used * physical eraseblocks with low erase counter to free physical eraseblocks @@ -43,34 +43,36 @@ * The 'ubi_wl_get_peb()' function accepts data type hints which help to pick * an "optimal" physical eraseblock. For example, when it is known that the * physical eraseblock will be "put" soon because it contains short-term data, - * the WL unit may pick a free physical eraseblock with low erase counter, and - * so forth. + * the WL sub-system may pick a free physical eraseblock with low erase + * counter, and so forth. * - * If the WL unit fails to erase a physical eraseblock, it marks it as bad. + * If the WL sub-system fails to erase a physical eraseblock, it marks it as + * bad. * - * This unit is also responsible for scrubbing. If a bit-flip is detected in a - * physical eraseblock, it has to be moved. Technically this is the same as - * moving it for wear-leveling reasons. + * This sub-system is also responsible for scrubbing. If a bit-flip is detected + * in a physical eraseblock, it has to be moved. Technically this is the same + * as moving it for wear-leveling reasons. * - * As it was said, for the UBI unit all physical eraseblocks are either "free" - * or "used". Free eraseblock are kept in the @wl->free RB-tree, while used - * eraseblocks are kept in a set of different RB-trees: @wl->used, + * As it was said, for the UBI sub-system all physical eraseblocks are either + * "free" or "used". Free eraseblock are kept in the @wl->free RB-tree, while + * used eraseblocks are kept in a set of different RB-trees: @wl->used, * @wl->prot.pnum, @wl->prot.aec, and @wl->scrub. * * Note, in this implementation, we keep a small in-RAM object for each physical * eraseblock. This is surely not a scalable solution. But it appears to be good * enough for moderately large flashes and it is simple. In future, one may - * re-work this unit and make it more scalable. + * re-work this sub-system and make it more scalable. * - * At the moment this unit does not utilize the sequence number, which was - * introduced relatively recently. But it would be wise to do this because the - * sequence number of a logical eraseblock characterizes how old is it. For + * At the moment this sub-system does not utilize the sequence number, which + * was introduced relatively recently. But it would be wise to do this because + * the sequence number of a logical eraseblock characterizes how old is it. For * example, when we move a PEB with low erase counter, and we need to pick the * target PEB, we pick a PEB with the highest EC if our PEB is "old" and we * pick target PEB with an average EC if our PEB is not very "old". This is a - * room for future re-works of the WL unit. + * room for future re-works of the WL sub-system. * - * FIXME: looks too complex, should be simplified (later). + * Note: the stuff with protection trees looks too complex and is difficult to + * understand. Should be fixed. */ #include @@ -92,20 +94,21 @@ /* * Maximum difference between two erase counters. If this threshold is - * exceeded, the WL unit starts moving data from used physical eraseblocks with - * low erase counter to free physical eraseblocks with high erase counter. + * exceeded, the WL sub-system starts moving data from used physical + * eraseblocks with low erase counter to free physical eraseblocks with high + * erase counter. */ #define UBI_WL_THRESHOLD CONFIG_MTD_UBI_WL_THRESHOLD /* - * When a physical eraseblock is moved, the WL unit has to pick the target + * When a physical eraseblock is moved, the WL sub-system has to pick the target * physical eraseblock to move to. The simplest way would be just to pick the * one with the highest erase counter. But in certain workloads this could lead * to an unlimited wear of one or few physical eraseblock. Indeed, imagine a * situation when the picked physical eraseblock is constantly erased after the * data is written to it. So, we have a constant which limits the highest erase - * counter of the free physical eraseblock to pick. Namely, the WL unit does - * not pick eraseblocks with erase counter greater then the lowest erase + * counter of the free physical eraseblock to pick. Namely, the WL sub-system + * does not pick eraseblocks with erase counter greater then the lowest erase * counter plus %WL_FREE_MAX_DIFF. */ #define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD) @@ -123,11 +126,11 @@ * @abs_ec: the absolute erase counter value when the protection ends * @e: the wear-leveling entry of the physical eraseblock under protection * - * When the WL unit returns a physical eraseblock, the physical eraseblock is - * protected from being moved for some "time". For this reason, the physical - * eraseblock is not directly moved from the @wl->free tree to the @wl->used - * tree. There is one more tree in between where this physical eraseblock is - * temporarily stored (@wl->prot). + * When the WL sub-system returns a physical eraseblock, the physical + * eraseblock is protected from being moved for some "time". For this reason, + * the physical eraseblock is not directly moved from the @wl->free tree to the + * @wl->used tree. There is one more tree in between where this physical + * eraseblock is temporarily stored (@wl->prot). * * All this protection stuff is needed because: * o we don't want to move physical eraseblocks just after we have given them @@ -175,7 +178,6 @@ struct ubi_wl_prot_entry { * @list: a link in the list of pending works * @func: worker function * @priv: private data of the worker function - * * @e: physical eraseblock to erase * @torture: if the physical eraseblock has to be tortured * @@ -1136,7 +1138,7 @@ out_ro: } /** - * ubi_wl_put_peb - return a physical eraseblock to the wear-leveling unit. + * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system. * @ubi: UBI device description object * @pnum: physical eraseblock to return * @torture: if this physical eraseblock has to be tortured @@ -1175,11 +1177,11 @@ retry: /* * User is putting the physical eraseblock which was selected * as the target the data is moved to. It may happen if the EBA - * unit already re-mapped the LEB in 'ubi_eba_copy_leb()' but - * the WL unit has not put the PEB to the "used" tree yet, but - * it is about to do this. So we just set a flag which will - * tell the WL worker that the PEB is not needed anymore and - * should be scheduled for erasure. + * sub-system already re-mapped the LEB in 'ubi_eba_copy_leb()' + * but the WL sub-system has not put the PEB to the "used" tree + * yet, but it is about to do this. So we just set a flag which + * will tell the WL worker that the PEB is not needed anymore + * and should be scheduled for erasure. */ dbg_wl("PEB %d is the target of data moving", pnum); ubi_assert(!ubi->move_to_put); @@ -1425,8 +1427,7 @@ static void cancel_pending(struct ubi_device *ubi) } /** - * ubi_wl_init_scan - initialize the wear-leveling unit using scanning - * information. + * ubi_wl_init_scan - initialize the WL sub-system using scanning information. * @ubi: UBI device description object * @si: scanning information * @@ -1583,13 +1584,12 @@ static void protection_trees_destroy(struct ubi_device *ubi) } /** - * ubi_wl_close - close the wear-leveling unit. + * ubi_wl_close - close the wear-leveling sub-system. * @ubi: UBI device description object */ void ubi_wl_close(struct ubi_device *ubi) { - dbg_wl("close the UBI wear-leveling unit"); - + dbg_wl("close the WL sub-system"); cancel_pending(ubi); protection_trees_destroy(ubi); tree_destroy(&ubi->used); diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h index 83302bbbddb4..6316fafe5c2a 100644 --- a/include/linux/mtd/ubi.h +++ b/include/linux/mtd/ubi.h @@ -45,13 +45,13 @@ enum { * @size: how many physical eraseblocks are reserved for this volume * @used_bytes: how many bytes of data this volume contains * @used_ebs: how many physical eraseblocks of this volume actually contain any - * data + * data * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) * @corrupted: non-zero if the volume is corrupted (static volumes only) * @upd_marker: non-zero if the volume has update marker set * @alignment: volume alignment * @usable_leb_size: how many bytes are available in logical eraseblocks of - * this volume + * this volume * @name_len: volume name length * @name: volume name * @cdev: UBI volume character device major and minor numbers -- cgit v1.2.3-58-ga151 From c8566350a3229ca505b84313c65d1403b4d0cbfc Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 16 Jul 2008 17:40:22 +0300 Subject: UBI: fix and re-work debugging stuff Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 2 +- drivers/mtd/ubi/cdev.c | 26 ++++---- drivers/mtd/ubi/debug.c | 160 +++++++++++++++++++++++++---------------------- drivers/mtd/ubi/debug.h | 68 +++++++++++++------- drivers/mtd/ubi/gluebi.c | 10 +-- drivers/mtd/ubi/io.c | 4 +- drivers/mtd/ubi/kapi.c | 20 +++--- drivers/mtd/ubi/scan.c | 2 +- drivers/mtd/ubi/upd.c | 16 ++--- drivers/mtd/ubi/vmt.c | 73 ++++++++++----------- drivers/mtd/ubi/vtbl.c | 2 +- 11 files changed, 206 insertions(+), 177 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 27271fe32e02..7210e1da1fcb 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -403,7 +403,7 @@ static int uif_init(struct ubi_device *ubi) ubi_assert(MINOR(dev) == 0); cdev_init(&ubi->cdev, &ubi_cdev_operations); - dbg_msg("%s major is %u", ubi->ubi_name, MAJOR(dev)); + dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev)); ubi->cdev.owner = THIS_MODULE; err = cdev_add(&ubi->cdev, dev, 1); diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 4fb84e3e6502..7c19918cc914 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -116,7 +116,7 @@ static int vol_cdev_open(struct inode *inode, struct file *file) else mode = UBI_READONLY; - dbg_msg("open volume %d, mode %d", vol_id, mode); + dbg_gen("open volume %d, mode %d", vol_id, mode); desc = ubi_open_volume(ubi_num, vol_id, mode); unlock_kernel(); @@ -132,7 +132,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file) struct ubi_volume_desc *desc = file->private_data; struct ubi_volume *vol = desc->vol; - dbg_msg("release volume %d, mode %d", vol->vol_id, desc->mode); + dbg_gen("release volume %d, mode %d", vol->vol_id, desc->mode); if (vol->updating) { ubi_warn("update of volume %d not finished, volume is damaged", @@ -141,7 +141,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file) vol->updating = 0; vfree(vol->upd_buf); } else if (vol->changing_leb) { - dbg_msg("only %lld of %lld bytes received for atomic LEB change" + dbg_gen("only %lld of %lld bytes received for atomic LEB change" " for volume %d:%d, cancel", vol->upd_received, vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id); vol->changing_leb = 0; @@ -183,7 +183,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin) return -EINVAL; } - dbg_msg("seek volume %d, offset %lld, origin %d, new offset %lld", + dbg_gen("seek volume %d, offset %lld, origin %d, new offset %lld", vol->vol_id, offset, origin, new_offset); file->f_pos = new_offset; @@ -201,7 +201,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, void *tbuf; uint64_t tmp; - dbg_msg("read %zd bytes from offset %lld of volume %d", + dbg_gen("read %zd bytes from offset %lld of volume %d", count, *offp, vol->vol_id); if (vol->updating) { @@ -216,7 +216,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, return 0; if (vol->corrupted) - dbg_msg("read from corrupted volume %d", vol->vol_id); + dbg_gen("read from corrupted volume %d", vol->vol_id); if (*offp + count > vol->used_bytes) count_save = count = vol->used_bytes - *offp; @@ -285,7 +285,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, char *tbuf; uint64_t tmp; - dbg_msg("requested: write %zd bytes to offset %lld of volume %u", + dbg_gen("requested: write %zd bytes to offset %lld of volume %u", count, *offp, vol->vol_id); if (vol->vol_type == UBI_STATIC_VOLUME) @@ -514,7 +514,7 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, break; } - dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); + dbg_gen("erase LEB %d:%d", vol->vol_id, lnum); err = ubi_eba_unmap_leb(ubi, vol, lnum); if (err) break; @@ -626,7 +626,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, { struct ubi_mkvol_req req; - dbg_msg("create volume"); + dbg_gen("create volume"); err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); if (err) { err = -EFAULT; @@ -656,7 +656,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, { int vol_id; - dbg_msg("remove volume"); + dbg_gen("remove volume"); err = get_user(vol_id, (__user int32_t *)argp); if (err) { err = -EFAULT; @@ -689,7 +689,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, uint64_t tmp; struct ubi_rsvol_req req; - dbg_msg("re-size volume"); + dbg_gen("re-size volume"); err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); if (err) { err = -EFAULT; @@ -742,7 +742,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, struct ubi_attach_req req; struct mtd_info *mtd; - dbg_msg("attach MTD device"); + dbg_gen("attach MTD device"); err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req)); if (err) { err = -EFAULT; @@ -782,7 +782,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, { int ubi_num; - dbg_msg("dettach MTD device"); + dbg_gen("dettach MTD device"); err = get_user(ubi_num, (__user int32_t *)argp); if (err) { err = -EFAULT; diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 56956ec2845f..21e0d7d76a44 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -24,7 +24,7 @@ * changes. */ -#ifdef CONFIG_MTD_UBI_DEBUG_MSG +#ifdef CONFIG_MTD_UBI_DEBUG #include "ubi.h" @@ -34,14 +34,19 @@ */ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) { - dbg_msg("erase counter header dump:"); - dbg_msg("magic %#08x", be32_to_cpu(ec_hdr->magic)); - dbg_msg("version %d", (int)ec_hdr->version); - dbg_msg("ec %llu", (long long)be64_to_cpu(ec_hdr->ec)); - dbg_msg("vid_hdr_offset %d", be32_to_cpu(ec_hdr->vid_hdr_offset)); - dbg_msg("data_offset %d", be32_to_cpu(ec_hdr->data_offset)); - dbg_msg("hdr_crc %#08x", be32_to_cpu(ec_hdr->hdr_crc)); - dbg_msg("erase counter header hexdump:"); + printk(KERN_DEBUG "Erase counter header dump:\n"); + printk(KERN_DEBUG "\tmagic %#08x\n", + be32_to_cpu(ec_hdr->magic)); + printk(KERN_DEBUG "\tversion %d\n", (int)ec_hdr->version); + printk(KERN_DEBUG "\tec %llu\n", + (long long)be64_to_cpu(ec_hdr->ec)); + printk(KERN_DEBUG "\tvid_hdr_offset %d\n", + be32_to_cpu(ec_hdr->vid_hdr_offset)); + printk(KERN_DEBUG "\tdata_offset %d\n", + be32_to_cpu(ec_hdr->data_offset)); + printk(KERN_DEBUG "\thdr_crc %#08x\n", + be32_to_cpu(ec_hdr->hdr_crc)); + printk(KERN_DEBUG "erase counter header hexdump:\n"); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, ec_hdr, UBI_EC_HDR_SIZE, 1); } @@ -52,22 +57,24 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) */ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) { - dbg_msg("volume identifier header dump:"); - dbg_msg("magic %08x", be32_to_cpu(vid_hdr->magic)); - dbg_msg("version %d", (int)vid_hdr->version); - dbg_msg("vol_type %d", (int)vid_hdr->vol_type); - dbg_msg("copy_flag %d", (int)vid_hdr->copy_flag); - dbg_msg("compat %d", (int)vid_hdr->compat); - dbg_msg("vol_id %d", be32_to_cpu(vid_hdr->vol_id)); - dbg_msg("lnum %d", be32_to_cpu(vid_hdr->lnum)); - dbg_msg("leb_ver %u", be32_to_cpu(vid_hdr->leb_ver)); - dbg_msg("data_size %d", be32_to_cpu(vid_hdr->data_size)); - dbg_msg("used_ebs %d", be32_to_cpu(vid_hdr->used_ebs)); - dbg_msg("data_pad %d", be32_to_cpu(vid_hdr->data_pad)); - dbg_msg("sqnum %llu", + printk(KERN_DEBUG "Volume identifier header dump:\n"); + printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic)); + printk(KERN_DEBUG "\tversion %d\n", (int)vid_hdr->version); + printk(KERN_DEBUG "\tvol_type %d\n", (int)vid_hdr->vol_type); + printk(KERN_DEBUG "\tcopy_flag %d\n", (int)vid_hdr->copy_flag); + printk(KERN_DEBUG "\tcompat %d\n", (int)vid_hdr->compat); + printk(KERN_DEBUG "\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id)); + printk(KERN_DEBUG "\tlnum %d\n", be32_to_cpu(vid_hdr->lnum)); + printk(KERN_DEBUG "\tleb_ver %u\n", be32_to_cpu(vid_hdr->leb_ver)); + printk(KERN_DEBUG "\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size)); + printk(KERN_DEBUG "\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs)); + printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad)); + printk(KERN_DEBUG "\tsqnum %llu\n", (unsigned long long)be64_to_cpu(vid_hdr->sqnum)); - dbg_msg("hdr_crc %08x", be32_to_cpu(vid_hdr->hdr_crc)); - dbg_msg("volume identifier header hexdump:"); + printk(KERN_DEBUG "\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc)); + printk(KERN_DEBUG "Volume identifier header hexdump:\n"); + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, + vid_hdr, UBI_VID_HDR_SIZE, 1); } /** @@ -76,27 +83,27 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) */ void ubi_dbg_dump_vol_info(const struct ubi_volume *vol) { - dbg_msg("volume information dump:"); - dbg_msg("vol_id %d", vol->vol_id); - dbg_msg("reserved_pebs %d", vol->reserved_pebs); - dbg_msg("alignment %d", vol->alignment); - dbg_msg("data_pad %d", vol->data_pad); - dbg_msg("vol_type %d", vol->vol_type); - dbg_msg("name_len %d", vol->name_len); - dbg_msg("usable_leb_size %d", vol->usable_leb_size); - dbg_msg("used_ebs %d", vol->used_ebs); - dbg_msg("used_bytes %lld", vol->used_bytes); - dbg_msg("last_eb_bytes %d", vol->last_eb_bytes); - dbg_msg("corrupted %d", vol->corrupted); - dbg_msg("upd_marker %d", vol->upd_marker); + printk(KERN_DEBUG "Volume information dump:\n"); + printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id); + printk(KERN_DEBUG "\treserved_pebs %d\n", vol->reserved_pebs); + printk(KERN_DEBUG "\talignment %d\n", vol->alignment); + printk(KERN_DEBUG "\tdata_pad %d\n", vol->data_pad); + printk(KERN_DEBUG "\tvol_type %d\n", vol->vol_type); + printk(KERN_DEBUG "\tname_len %d\n", vol->name_len); + printk(KERN_DEBUG "\tusable_leb_size %d\n", vol->usable_leb_size); + printk(KERN_DEBUG "\tused_ebs %d\n", vol->used_ebs); + printk(KERN_DEBUG "\tused_bytes %lld\n", vol->used_bytes); + printk(KERN_DEBUG "\tlast_eb_bytes %d\n", vol->last_eb_bytes); + printk(KERN_DEBUG "\tcorrupted %d\n", vol->corrupted); + printk(KERN_DEBUG "\tupd_marker %d\n", vol->upd_marker); if (vol->name_len <= UBI_VOL_NAME_MAX && strnlen(vol->name, vol->name_len + 1) == vol->name_len) { - dbg_msg("name %s", vol->name); + printk(KERN_DEBUG "\tname %s\n", vol->name); } else { - dbg_msg("the 1st 5 characters of the name: %c%c%c%c%c", - vol->name[0], vol->name[1], vol->name[2], - vol->name[3], vol->name[4]); + printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n", + vol->name[0], vol->name[1], vol->name[2], + vol->name[3], vol->name[4]); } } @@ -109,28 +116,29 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) { int name_len = be16_to_cpu(r->name_len); - dbg_msg("volume table record %d dump:", idx); - dbg_msg("reserved_pebs %d", be32_to_cpu(r->reserved_pebs)); - dbg_msg("alignment %d", be32_to_cpu(r->alignment)); - dbg_msg("data_pad %d", be32_to_cpu(r->data_pad)); - dbg_msg("vol_type %d", (int)r->vol_type); - dbg_msg("upd_marker %d", (int)r->upd_marker); - dbg_msg("name_len %d", name_len); + printk(KERN_DEBUG "Volume table record %d dump:\n", idx); + printk(KERN_DEBUG "\treserved_pebs %d\n", + be32_to_cpu(r->reserved_pebs)); + printk(KERN_DEBUG "\talignment %d\n", be32_to_cpu(r->alignment)); + printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(r->data_pad)); + printk(KERN_DEBUG "\tvol_type %d\n", (int)r->vol_type); + printk(KERN_DEBUG "\tupd_marker %d\n", (int)r->upd_marker); + printk(KERN_DEBUG "\tname_len %d\n", name_len); if (r->name[0] == '\0') { - dbg_msg("name NULL"); + printk(KERN_DEBUG "\tname NULL\n"); return; } if (name_len <= UBI_VOL_NAME_MAX && strnlen(&r->name[0], name_len + 1) == name_len) { - dbg_msg("name %s", &r->name[0]); + printk(KERN_DEBUG "\tname %s\n", &r->name[0]); } else { - dbg_msg("1st 5 characters of the name: %c%c%c%c%c", + printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n", r->name[0], r->name[1], r->name[2], r->name[3], r->name[4]); } - dbg_msg("crc %#08x", be32_to_cpu(r->crc)); + printk(KERN_DEBUG "\tcrc %#08x\n", be32_to_cpu(r->crc)); } /** @@ -139,15 +147,15 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) */ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) { - dbg_msg("volume scanning information dump:"); - dbg_msg("vol_id %d", sv->vol_id); - dbg_msg("highest_lnum %d", sv->highest_lnum); - dbg_msg("leb_count %d", sv->leb_count); - dbg_msg("compat %d", sv->compat); - dbg_msg("vol_type %d", sv->vol_type); - dbg_msg("used_ebs %d", sv->used_ebs); - dbg_msg("last_data_size %d", sv->last_data_size); - dbg_msg("data_pad %d", sv->data_pad); + printk(KERN_DEBUG "Volume scanning information dump:\n"); + printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id); + printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum); + printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count); + printk(KERN_DEBUG "\tcompat %d\n", sv->compat); + printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type); + printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs); + printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size); + printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad); } /** @@ -157,14 +165,14 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) */ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type) { - dbg_msg("eraseblock scanning information dump:"); - dbg_msg("ec %d", seb->ec); - dbg_msg("pnum %d", seb->pnum); + printk(KERN_DEBUG "eraseblock scanning information dump:\n"); + printk(KERN_DEBUG "\tec %d\n", seb->ec); + printk(KERN_DEBUG "\tpnum %d\n", seb->pnum); if (type == 0) { - dbg_msg("lnum %d", seb->lnum); - dbg_msg("scrub %d", seb->scrub); - dbg_msg("sqnum %llu", seb->sqnum); - dbg_msg("leb_ver %u", seb->leb_ver); + printk(KERN_DEBUG "\tlnum %d\n", seb->lnum); + printk(KERN_DEBUG "\tscrub %d\n", seb->scrub); + printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum); + printk(KERN_DEBUG "\tleb_ver %u\n", seb->leb_ver); } } @@ -176,16 +184,16 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) { char nm[17]; - dbg_msg("volume creation request dump:"); - dbg_msg("vol_id %d", req->vol_id); - dbg_msg("alignment %d", req->alignment); - dbg_msg("bytes %lld", (long long)req->bytes); - dbg_msg("vol_type %d", req->vol_type); - dbg_msg("name_len %d", req->name_len); + printk(KERN_DEBUG "Volume creation request dump:\n"); + printk(KERN_DEBUG "\tvol_id %d\n", req->vol_id); + printk(KERN_DEBUG "\talignment %d\n", req->alignment); + printk(KERN_DEBUG "\tbytes %lld\n", (long long)req->bytes); + printk(KERN_DEBUG "\tvol_type %d\n", req->vol_type); + printk(KERN_DEBUG "\tname_len %d\n", req->name_len); memcpy(nm, req->name, 16); nm[16] = 0; - dbg_msg("the 1st 16 characters of the name: %s", nm); + printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm); } -#endif /* CONFIG_MTD_UBI_DEBUG_MSG */ +#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 7d8d77c31dfe..78e914d23ece 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -24,21 +24,16 @@ #ifdef CONFIG_MTD_UBI_DEBUG #include -#define ubi_assert(expr) BUG_ON(!(expr)) #define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__) -#else -#define ubi_assert(expr) ({}) -#define dbg_err(fmt, ...) ({}) -#endif -#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT -#define DBG_DISABLE_BGT 1 -#else -#define DBG_DISABLE_BGT 0 -#endif +#define ubi_assert(expr) do { \ + if (unlikely(!(expr))) { \ + printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \ + __func__, __LINE__, current->pid); \ + ubi_dbg_dump_stack(); \ + } \ +} while (0) -#ifdef CONFIG_MTD_UBI_DEBUG_MSG -/* Generic debugging message */ #define dbg_msg(fmt, ...) \ printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \ current->pid, __func__, ##__VA_ARGS__) @@ -61,19 +56,12 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv); void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type); void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); +#ifdef CONFIG_MTD_UBI_DEBUG_MSG +/* General debugging messages */ +#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) #else - -#define dbg_msg(fmt, ...) ({}) -#define ubi_dbg_dump_stack() ({}) -#define ubi_dbg_dump_ec_hdr(ec_hdr) ({}) -#define ubi_dbg_dump_vid_hdr(vid_hdr) ({}) -#define ubi_dbg_dump_vol_info(vol) ({}) -#define ubi_dbg_dump_vtbl_record(r, idx) ({}) -#define ubi_dbg_dump_sv(sv) ({}) -#define ubi_dbg_dump_seb(seb, type) ({}) -#define ubi_dbg_dump_mkvol_req(req) ({}) - -#endif /* CONFIG_MTD_UBI_DEBUG_MSG */ +#define dbg_gen(fmt, ...) ({}) +#endif #ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA /* Messages from the eraseblock association sub-system */ @@ -105,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); #define UBI_IO_DEBUG 0 #endif +#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT +#define DBG_DISABLE_BGT 1 +#else +#define DBG_DISABLE_BGT 0 +#endif + #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS /** * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip. @@ -149,4 +143,30 @@ static inline int ubi_dbg_is_erase_failure(void) #define ubi_dbg_is_erase_failure() 0 #endif +#else + +#define ubi_assert(expr) ({}) +#define dbg_err(fmt, ...) ({}) +#define dbg_msg(fmt, ...) ({}) +#define dbg_gen(fmt, ...) ({}) +#define dbg_eba(fmt, ...) ({}) +#define dbg_wl(fmt, ...) ({}) +#define dbg_io(fmt, ...) ({}) +#define dbg_bld(fmt, ...) ({}) +#define ubi_dbg_dump_stack() ({}) +#define ubi_dbg_dump_ec_hdr(ec_hdr) ({}) +#define ubi_dbg_dump_vid_hdr(vid_hdr) ({}) +#define ubi_dbg_dump_vol_info(vol) ({}) +#define ubi_dbg_dump_vtbl_record(r, idx) ({}) +#define ubi_dbg_dump_sv(sv) ({}) +#define ubi_dbg_dump_seb(seb, type) ({}) +#define ubi_dbg_dump_mkvol_req(req) ({}) + +#define UBI_IO_DEBUG 0 +#define DBG_DISABLE_BGT 0 +#define ubi_dbg_is_bitflip() 0 +#define ubi_dbg_is_write_failure() 0 +#define ubi_dbg_is_erase_failure() 0 + +#endif /* !CONFIG_MTD_UBI_DEBUG */ #endif /* !__UBI_DEBUG_H__ */ diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index ae76ab638b2f..49f52dceea93 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c @@ -111,7 +111,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, struct ubi_device *ubi; uint64_t tmp = from; - dbg_msg("read %zd bytes from offset %lld", len, from); + dbg_gen("read %zd bytes from offset %lld", len, from); if (len < 0 || from < 0 || from + len > mtd->size) return -EINVAL; @@ -162,7 +162,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, struct ubi_device *ubi; uint64_t tmp = to; - dbg_msg("write %zd bytes to offset %lld", len, to); + dbg_gen("write %zd bytes to offset %lld", len, to); if (len < 0 || to < 0 || len + to > mtd->size) return -EINVAL; @@ -215,7 +215,7 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr) struct ubi_volume *vol; struct ubi_device *ubi; - dbg_msg("erase %u bytes at offset %u", instr->len, instr->addr); + dbg_gen("erase %u bytes at offset %u", instr->len, instr->addr); if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize) return -EINVAL; @@ -304,7 +304,7 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol) return -ENFILE; } - dbg_msg("added mtd%d (\"%s\"), size %u, EB size %u", + dbg_gen("added mtd%d (\"%s\"), size %u, EB size %u", mtd->index, mtd->name, mtd->size, mtd->erasesize); return 0; } @@ -322,7 +322,7 @@ int ubi_destroy_gluebi(struct ubi_volume *vol) int err; struct mtd_info *mtd = &vol->gluebi_mtd; - dbg_msg("remove mtd%d", mtd->index); + dbg_gen("remove mtd%d", mtd->index); err = del_mtd_device(mtd); if (err) return err; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 561e7b2f96cb..27b9c2c2fc60 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -187,7 +187,7 @@ retry: ubi_assert(len == read); if (ubi_dbg_is_bitflip()) { - dbg_msg("bit-flip (emulated)"); + dbg_gen("bit-flip (emulated)"); err = UBI_IO_BITFLIPS; } } @@ -1256,7 +1256,7 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, fail: ubi_err("paranoid check failed for PEB %d", pnum); - dbg_msg("hex dump of the %d-%d region", offset, offset + len); + ubi_msg("hex dump of the %d-%d region", offset, offset + len); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, ubi->dbg_peb_buf, len, 1); err = 1; diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index e65c8e0bcd5d..5d9bcf109c13 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -106,7 +106,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) struct ubi_device *ubi; struct ubi_volume *vol; - dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode); + dbg_gen("open device %d volume %d, mode %d", ubi_num, vol_id, mode); if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) return ERR_PTR(-EINVAL); @@ -215,7 +215,7 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, struct ubi_device *ubi; struct ubi_volume_desc *ret; - dbg_msg("open volume %s, mode %d", name, mode); + dbg_gen("open volume %s, mode %d", name, mode); if (!name) return ERR_PTR(-EINVAL); @@ -266,7 +266,7 @@ void ubi_close_volume(struct ubi_volume_desc *desc) struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; - dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode); + dbg_gen("close volume %d, mode %d", vol->vol_id, desc->mode); spin_lock(&ubi->volumes_lock); switch (desc->mode) { @@ -323,7 +323,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, struct ubi_device *ubi = vol->ubi; int err, vol_id = vol->vol_id; - dbg_msg("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); + dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 || lnum >= vol->used_ebs || offset < 0 || len < 0 || @@ -388,7 +388,7 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, struct ubi_device *ubi = vol->ubi; int vol_id = vol->vol_id; - dbg_msg("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset); + dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset); if (vol_id < 0 || vol_id >= ubi->vtbl_slots) return -EINVAL; @@ -438,7 +438,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, struct ubi_device *ubi = vol->ubi; int vol_id = vol->vol_id; - dbg_msg("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum); + dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum); if (vol_id < 0 || vol_id >= ubi->vtbl_slots) return -EINVAL; @@ -482,7 +482,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) struct ubi_device *ubi = vol->ubi; int err; - dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); + dbg_gen("erase LEB %d:%d", vol->vol_id, lnum); if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; @@ -542,7 +542,7 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum) struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; - dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); + dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; @@ -579,7 +579,7 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; - dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); + dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; @@ -621,7 +621,7 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum) { struct ubi_volume *vol = desc->vol; - dbg_msg("test LEB %d:%d", vol->vol_id, lnum); + dbg_gen("test LEB %d:%d", vol->vol_id, lnum); if (lnum < 0 || lnum >= vol->reserved_pebs) return -EINVAL; diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 892c2ba49777..40eca9ce5fab 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -932,7 +932,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) for (pnum = 0; pnum < ubi->peb_count; pnum++) { cond_resched(); - dbg_msg("process PEB %d", pnum); + dbg_gen("process PEB %d", pnum); err = process_eb(ubi, si, pnum); if (err < 0) goto out_vidh; diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 6fa1ab3f2a70..1230a5e1b530 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -56,11 +56,11 @@ static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol) int err; struct ubi_vtbl_record vtbl_rec; - dbg_msg("set update marker for volume %d", vol->vol_id); + dbg_gen("set update marker for volume %d", vol->vol_id); if (vol->upd_marker) { ubi_assert(ubi->vtbl[vol->vol_id].upd_marker); - dbg_msg("already set"); + dbg_gen("already set"); return 0; } @@ -92,7 +92,7 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, uint64_t tmp; struct ubi_vtbl_record vtbl_rec; - dbg_msg("clear update marker for volume %d", vol->vol_id); + dbg_gen("clear update marker for volume %d", vol->vol_id); memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], sizeof(struct ubi_vtbl_record)); @@ -133,7 +133,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, int i, err; uint64_t tmp; - dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes); + dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes); ubi_assert(!vol->updating && !vol->changing_leb); vol->updating = 1; @@ -183,7 +183,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, { ubi_assert(!vol->updating && !vol->changing_leb); - dbg_msg("start changing LEB %d:%d, %u bytes", + dbg_gen("start changing LEB %d:%d, %u bytes", vol->vol_id, req->lnum, req->bytes); if (req->bytes == 0) return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0, @@ -242,7 +242,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, memset(buf + len, 0xFF, l - len); len = ubi_calc_data_len(ubi, buf, l); if (len == 0) { - dbg_msg("all %d bytes contain 0xFF - skip", len); + dbg_gen("all %d bytes contain 0xFF - skip", len); return 0; } @@ -283,7 +283,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, uint64_t tmp; int lnum, offs, err = 0, len, to_write = count; - dbg_msg("write %d of %lld bytes, %lld already passed", + dbg_gen("write %d of %lld bytes, %lld already passed", count, vol->upd_bytes, vol->upd_received); if (ubi->ro_mode) @@ -400,7 +400,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, { int err; - dbg_msg("write %d of %lld bytes, %lld already passed", + dbg_gen("write %d of %lld bytes, %lld already passed", count, vol->upd_bytes, vol->upd_received); if (ubi->ro_mode) diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index bfa7c5d2e064..2cd886a5adac 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -28,9 +28,9 @@ #include "ubi.h" #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID -static void paranoid_check_volumes(struct ubi_device *ubi); +static int paranoid_check_volumes(struct ubi_device *ubi); #else -#define paranoid_check_volumes(ubi) +#define paranoid_check_volumes(ubi) 0 #endif static ssize_t vol_attribute_show(struct device *dev, @@ -218,7 +218,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) spin_lock(&ubi->volumes_lock); if (vol_id == UBI_VOL_NUM_AUTO) { /* Find unused volume ID */ - dbg_msg("search for vacant volume ID"); + dbg_gen("search for vacant volume ID"); for (i = 0; i < ubi->vtbl_slots; i++) if (!ubi->volumes[i]) { vol_id = i; @@ -233,7 +233,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) req->vol_id = vol_id; } - dbg_msg("volume ID %d, %llu bytes, type %d, name %s", + dbg_gen("volume ID %d, %llu bytes, type %d, name %s", vol_id, (unsigned long long)req->bytes, (int)req->vol_type, req->name); @@ -361,8 +361,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ubi->vol_count += 1; spin_unlock(&ubi->volumes_lock); - paranoid_check_volumes(ubi); - return 0; + err = paranoid_check_volumes(ubi); + return err; out_sysfs: /* @@ -414,7 +414,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) struct ubi_device *ubi = vol->ubi; int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs; - dbg_msg("remove UBI volume %d", vol_id); + dbg_gen("remove UBI volume %d", vol_id); ubi_assert(desc->mode == UBI_EXCLUSIVE); ubi_assert(vol == ubi->volumes[vol_id]); @@ -465,8 +465,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) ubi->vol_count -= 1; spin_unlock(&ubi->volumes_lock); - paranoid_check_volumes(ubi); - return 0; + err = paranoid_check_volumes(ubi); + return err; out_err: ubi_err("cannot remove volume %d, error %d", vol_id, err); @@ -497,7 +497,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) if (ubi->ro_mode) return -EROFS; - dbg_msg("re-size volume %d to from %d to %d PEBs", + dbg_gen("re-size volume %d to from %d to %d PEBs", vol_id, vol->reserved_pebs, reserved_pebs); if (vol->vol_type == UBI_STATIC_VOLUME && @@ -586,8 +586,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) (long long)vol->used_ebs * vol->usable_leb_size; } - paranoid_check_volumes(ubi); - return 0; + err = paranoid_check_volumes(ubi); + return err; out_acc: if (pebs > 0) { @@ -615,8 +615,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) int err, vol_id = vol->vol_id; dev_t dev; - dbg_msg("add volume %d", vol_id); - ubi_dbg_dump_vol_info(vol); + dbg_gen("add volume %d", vol_id); /* Register character device for the volume */ cdev_init(&vol->cdev, &ubi_vol_cdev_operations); @@ -650,8 +649,8 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) return err; } - paranoid_check_volumes(ubi); - return 0; + err = paranoid_check_volumes(ubi); + return err; out_gluebi: err = ubi_destroy_gluebi(vol); @@ -672,7 +671,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) { int err; - dbg_msg("free volume %d", vol->vol_id); + dbg_gen("free volume %d", vol->vol_id); ubi->volumes[vol->vol_id] = NULL; err = ubi_destroy_gluebi(vol); @@ -686,8 +685,10 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) * paranoid_check_volume - check volume information. * @ubi: UBI device description object * @vol_id: volume ID + * + * Returns zero if volume is all right and a a negative error code if not. */ -static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) +static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) { int idx = vol_id2idx(ubi, vol_id); int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; @@ -705,16 +706,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) goto fail; } spin_unlock(&ubi->volumes_lock); - return; - } - - if (vol->exclusive) { - /* - * The volume may be being created at the moment, do not check - * it (e.g., it may be in the middle of ubi_create_volume(). - */ - spin_unlock(&ubi->volumes_lock); - return; + return 0; } if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 || @@ -830,25 +822,34 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) } spin_unlock(&ubi->volumes_lock); - return; + return 0; fail: ubi_err("paranoid check failed for volume %d", vol_id); - ubi_dbg_dump_vol_info(vol); - ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); + if (vol) { + ubi_dbg_dump_vol_info(vol); + ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); + } spin_unlock(&ubi->volumes_lock); - BUG(); + return -EINVAL; } /** * paranoid_check_volumes - check information about all volumes. * @ubi: UBI device description object + * + * Returns zero if volumes are all right and a a negative error code if not. */ -static void paranoid_check_volumes(struct ubi_device *ubi) +static int paranoid_check_volumes(struct ubi_device *ubi) { - int i; + int i, err = 0; - for (i = 0; i < ubi->vtbl_slots; i++) - paranoid_check_volume(ubi, i); + for (i = 0; i < ubi->vtbl_slots; i++) { + err = paranoid_check_volume(ubi, i); + if (err) + break; + } + + return err; } #endif diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index d9af11a8682b..05fb72fd268f 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -371,7 +371,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, * to LEB 0. */ - dbg_msg("check layout volume"); + dbg_gen("check layout volume"); /* Read both LEB 0 and LEB 1 into memory */ ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { -- cgit v1.2.3-58-ga151 From f40ac9cdf6991287f19bdafe9b0752ee40137908 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 13 Jul 2008 21:47:47 +0300 Subject: UBI: implement multiple volumes rename Quite useful ioctl which allows to make atomic system upgrades. The idea belongs to Richard Titmuss Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 1 + drivers/mtd/ubi/cdev.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++- drivers/mtd/ubi/ubi.h | 33 ++++++++- drivers/mtd/ubi/vmt.c | 57 ++++++++++++--- drivers/mtd/ubi/vtbl.c | 51 +++++++++++++ include/mtd/ubi-user.h | 60 +++++++++++++++- 6 files changed, 375 insertions(+), 15 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 7210e1da1fcb..4418a2369b56 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -806,6 +806,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) mutex_init(&ubi->buf_mutex); mutex_init(&ubi->ckvol_mutex); + mutex_init(&ubi->mult_mutex); mutex_init(&ubi->volumes_mutex); spin_lock_init(&ubi->volumes_lock); diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 7c19918cc914..bc8199c6a9f5 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -605,6 +605,166 @@ static int verify_rsvol_req(const struct ubi_device *ubi, return 0; } +/** + * rename_volumes - rename UBI volumes. + * @ubi: UBI device description object + * @req: volumes re-name request + * + * This is a helper function for the volume re-name IOCTL which validates the + * the request, opens the volume and calls corresponding volumes management + * function. Returns zero in case of success and a negative error code in case + * of failure. + */ +static int rename_volumes(struct ubi_device *ubi, + struct ubi_rnvol_req *req) +{ + int i, n, err; + struct list_head rename_list; + struct ubi_rename_entry *re, *re1; + + if (req->count < 0 || req->count > UBI_MAX_RNVOL) + return -EINVAL; + + if (req->count == 0) + return 0; + + /* Validate volume IDs and names in the request */ + for (i = 0; i < req->count; i++) { + if (req->ents[i].vol_id < 0 || + req->ents[i].vol_id >= ubi->vtbl_slots) + return -EINVAL; + if (req->ents[i].name_len < 0) + return -EINVAL; + if (req->ents[i].name_len > UBI_VOL_NAME_MAX) + return -ENAMETOOLONG; + req->ents[i].name[req->ents[i].name_len] = '\0'; + n = strlen(req->ents[i].name); + if (n != req->ents[i].name_len) + err = -EINVAL; + } + + /* Make sure volume IDs and names are unique */ + for (i = 0; i < req->count - 1; i++) { + for (n = i + 1; n < req->count; n++) { + if (req->ents[i].vol_id == req->ents[n].vol_id) { + dbg_err("duplicated volume id %d", + req->ents[i].vol_id); + return -EINVAL; + } + if (!strcmp(req->ents[i].name, req->ents[n].name)) { + dbg_err("duplicated volume name \"%s\"", + req->ents[i].name); + return -EINVAL; + } + } + } + + /* Create the re-name list */ + INIT_LIST_HEAD(&rename_list); + for (i = 0; i < req->count; i++) { + int vol_id = req->ents[i].vol_id; + int name_len = req->ents[i].name_len; + const char *name = req->ents[i].name; + + re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); + if (!re) { + err = -ENOMEM; + goto out_free; + } + + re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); + if (IS_ERR(re->desc)) { + err = PTR_ERR(re->desc); + dbg_err("cannot open volume %d, error %d", vol_id, err); + kfree(re); + goto out_free; + } + + /* Skip this re-naming if the name does not really change */ + if (re->desc->vol->name_len == name_len && + !memcmp(re->desc->vol->name, name, name_len)) { + ubi_close_volume(re->desc); + kfree(re); + continue; + } + + re->new_name_len = name_len; + memcpy(re->new_name, name, name_len); + list_add_tail(&re->list, &rename_list); + dbg_msg("will rename volume %d from \"%s\" to \"%s\"", + vol_id, re->desc->vol->name, name); + } + + if (list_empty(&rename_list)) + return 0; + + /* Find out the volumes which have to be removed */ + list_for_each_entry(re, &rename_list, list) { + struct ubi_volume_desc *desc; + int no_remove_needed = 0; + + /* + * Volume @re->vol_id is going to be re-named to + * @re->new_name, while its current name is @name. If a volume + * with name @re->new_name currently exists, it has to be + * removed, unless it is also re-named in the request (@req). + */ + list_for_each_entry(re1, &rename_list, list) { + if (re->new_name_len == re1->desc->vol->name_len && + !memcmp(re->new_name, re1->desc->vol->name, + re1->desc->vol->name_len)) { + no_remove_needed = 1; + break; + } + } + + if (no_remove_needed) + continue; + + /* + * It seems we need to remove volume with name @re->new_name, + * if it exists. + */ + desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name, UBI_EXCLUSIVE); + if (IS_ERR(desc)) { + err = PTR_ERR(desc); + if (err == -ENODEV) + /* Re-naming into a non-existing volume name */ + continue; + + /* The volume exists but busy, or an error occurred */ + dbg_err("cannot open volume \"%s\", error %d", + re->new_name, err); + goto out_free; + } + + re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); + if (!re) { + err = -ENOMEM; + ubi_close_volume(desc); + goto out_free; + } + + re->remove = 1; + re->desc = desc; + list_add(&re->list, &rename_list); + dbg_msg("will remove volume %d, name \"%s\"", + re->desc->vol->vol_id, re->desc->vol->name); + } + + mutex_lock(&ubi->volumes_mutex); + err = ubi_rename_volumes(ubi, &rename_list); + mutex_unlock(&ubi->volumes_mutex); + +out_free: + list_for_each_entry_safe(re, re1, &rename_list, list) { + ubi_close_volume(re->desc); + list_del(&re->list); + kfree(re); + } + return err; +} + static int ubi_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -670,7 +830,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, } mutex_lock(&ubi->volumes_mutex); - err = ubi_remove_volume(desc); + err = ubi_remove_volume(desc, 0); mutex_unlock(&ubi->volumes_mutex); /* @@ -717,6 +877,32 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, break; } + /* Re-name volumes command */ + case UBI_IOCRNVOL: + { + struct ubi_rnvol_req *req; + + dbg_msg("re-name volumes"); + req = kmalloc(sizeof(struct ubi_rnvol_req), GFP_KERNEL); + if (!req) { + err = -ENOMEM; + break; + }; + + err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req)); + if (err) { + err = -EFAULT; + kfree(req); + break; + } + + mutex_lock(&ubi->mult_mutex); + err = rename_volumes(ubi, req); + mutex_unlock(&ubi->mult_mutex); + kfree(req); + break; + } + default: err = -ENOTTY; break; diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 1fc32c863b78..274c67916b34 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -131,6 +131,27 @@ struct ubi_ltree_entry { struct rw_semaphore mutex; }; +/** + * struct ubi_rename_entry - volume re-name description data structure. + * @new_name_len: new volume name length + * @new_name: new volume name + * @remove: if not zero, this volume should be removed, not re-named + * @desc: descriptor of the volume + * @list: links re-name entries into a list + * + * This data structure is utilized in the multiple volume re-name code. Namely, + * UBI first creates a list of &struct ubi_rename_entry objects from the + * &struct ubi_rnvol_req request object, and then utilizes this list to do all + * the job. + */ +struct ubi_rename_entry { + int new_name_len; + char new_name[UBI_VOL_NAME_MAX + 1]; + int remove; + struct ubi_volume_desc *desc; + struct list_head list; +}; + struct ubi_volume_desc; /** @@ -206,7 +227,7 @@ struct ubi_volume { int alignment; int data_pad; int name_len; - char name[UBI_VOL_NAME_MAX+1]; + char name[UBI_VOL_NAME_MAX + 1]; int upd_ebs; int ch_lnum; @@ -272,7 +293,7 @@ struct ubi_wl_entry; * @vtbl_size: size of the volume table in bytes * @vtbl: in-RAM volume table copy * @volumes_mutex: protects on-flash volume table and serializes volume - * changes, like creation, deletion, update, resize + * changes, like creation, deletion, update, re-size and re-name * * @max_ec: current highest erase counter value * @mean_ec: current mean erase counter value @@ -330,6 +351,8 @@ struct ubi_wl_entry; * @peb_buf1: a buffer of PEB size used for different purposes * @peb_buf2: another buffer of PEB size used for different purposes * @buf_mutex: proptects @peb_buf1 and @peb_buf2 + * @ckvol_mutex: serializes static volume checking when opening + * @mult_mutex: serializes operations on multiple volumes, like re-nameing * @dbg_peb_buf: buffer of PEB size used for debugging * @dbg_buf_mutex: proptects @dbg_peb_buf */ @@ -410,6 +433,7 @@ struct ubi_device { void *peb_buf2; struct mutex buf_mutex; struct mutex ckvol_mutex; + struct mutex mult_mutex; #ifdef CONFIG_MTD_UBI_DEBUG void *dbg_peb_buf; struct mutex dbg_buf_mutex; @@ -426,12 +450,15 @@ extern struct mutex ubi_devices_mutex; /* vtbl.c */ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, struct ubi_vtbl_record *vtbl_rec); +int ubi_vtbl_rename_volumes(struct ubi_device *ubi, + struct list_head *rename_list); int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si); /* vmt.c */ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req); -int ubi_remove_volume(struct ubi_volume_desc *desc); +int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl); int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs); +int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list); int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol); void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol); diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 2cd886a5adac..4be4014c70df 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -402,13 +402,14 @@ out_unlock: /** * ubi_remove_volume - remove volume. * @desc: volume descriptor + * @no_vtbl: do not change volume table if not zero * * This function removes volume described by @desc. The volume has to be opened * in "exclusive" mode. Returns zero in case of success and a negative error * code in case of failure. The caller has to have the @ubi->volumes_mutex * locked. */ -int ubi_remove_volume(struct ubi_volume_desc *desc) +int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; @@ -437,9 +438,11 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) if (err) goto out_err; - err = ubi_change_vtbl_record(ubi, vol_id, NULL); - if (err) - goto out_err; + if (!no_vtbl) { + err = ubi_change_vtbl_record(ubi, vol_id, NULL); + if (err) + goto out_err; + } for (i = 0; i < vol->reserved_pebs; i++) { err = ubi_eba_unmap_leb(ubi, vol, i); @@ -465,7 +468,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) ubi->vol_count -= 1; spin_unlock(&ubi->volumes_lock); - err = paranoid_check_volumes(ubi); + if (!no_vtbl) + err = paranoid_check_volumes(ubi); return err; out_err: @@ -601,6 +605,44 @@ out_free: return err; } +/** + * ubi_rename_volumes - re-name UBI volumes. + * @ubi: UBI device description object + * @renam_list: list of &struct ubi_rename_entry objects + * + * This function re-names or removes volumes specified in the re-name list. + * Returns zero in case of success and a negative error code in case of + * failure. + */ +int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list) +{ + int err; + struct ubi_rename_entry *re; + + err = ubi_vtbl_rename_volumes(ubi, rename_list); + if (err) + return err; + + list_for_each_entry(re, rename_list, list) { + if (re->remove) { + err = ubi_remove_volume(re->desc, 1); + if (err) + break; + } else { + struct ubi_volume *vol = re->desc->vol; + + spin_lock(&ubi->volumes_lock); + vol->name_len = re->new_name_len; + memcpy(vol->name, re->new_name, re->new_name_len + 1); + spin_unlock(&ubi->volumes_lock); + } + } + + if (!err) + paranoid_check_volumes(ubi); + return err; +} + /** * ubi_add_volume - add volume. * @ubi: UBI device description object @@ -826,10 +868,9 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) fail: ubi_err("paranoid check failed for volume %d", vol_id); - if (vol) { + if (vol) ubi_dbg_dump_vol_info(vol); - ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); - } + ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); spin_unlock(&ubi->volumes_lock); return -EINVAL; } diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 05fb72fd268f..23c5376234b2 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -114,6 +114,57 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, return 0; } +/** + * ubi_vtbl_rename_volumes - rename UBI volumes in the volume table. + * @ubi: UBI device description object + * @renam_list: list of &struct ubi_rename_entry objects + * + * This function re-names multiple volumes specified in @req in the volume + * table. Returns zero in case of success and a negative error code in case of + * failure. + */ +int ubi_vtbl_rename_volumes(struct ubi_device *ubi, + struct list_head *rename_list) +{ + int i, err; + struct ubi_rename_entry *re; + struct ubi_volume *layout_vol; + + list_for_each_entry(re, rename_list, list) { + uint32_t crc; + struct ubi_volume *vol = re->desc->vol; + struct ubi_vtbl_record *vtbl_rec = &ubi->vtbl[vol->vol_id]; + + if (re->remove) { + memcpy(vtbl_rec, &empty_vtbl_record, + sizeof(struct ubi_vtbl_record)); + continue; + } + + vtbl_rec->name_len = cpu_to_be16(re->new_name_len); + memcpy(vtbl_rec->name, re->new_name, re->new_name_len); + memset(vtbl_rec->name + re->new_name_len, 0, + UBI_VOL_NAME_MAX + 1 - re->new_name_len); + crc = crc32(UBI_CRC32_INIT, vtbl_rec, + UBI_VTBL_RECORD_SIZE_CRC); + vtbl_rec->crc = cpu_to_be32(crc); + } + + layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)]; + for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { + err = ubi_eba_unmap_leb(ubi, layout_vol, i); + if (err) + return err; + + err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, + ubi->vtbl_size, UBI_LONGTERM); + if (err) + return err; + } + + return 0; +} + /** * vtbl_check - check if volume table is not corrupted and contains sensible * data. diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index a7421f130cc0..e8e57c3dfcdb 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h @@ -58,6 +58,13 @@ * device should be used. A &struct ubi_rsvol_req object has to be properly * filled and a pointer to it has to be passed to the IOCTL. * + * UBI volumes re-name + * ~~~~~~~~~~~~~~~~~~~ + * + * To re-name several volumes atomically at one go, the %UBI_IOCRNVOL command + * of the UBI character device should be used. A &struct ubi_rnvol_req object + * has to be properly filled and a pointer to it has to be passed to the IOCTL. + * * UBI volume update * ~~~~~~~~~~~~~~~~~ * @@ -104,6 +111,8 @@ #define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t) /* Re-size an UBI volume */ #define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req) +/* Re-name volumes */ +#define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req) /* IOCTL commands of the UBI control character device */ @@ -128,6 +137,9 @@ /* Maximum MTD device name length supported by UBI */ #define MAX_UBI_MTD_NAME_LEN 127 +/* Maximum amount of UBI volumes that can be re-named at one go */ +#define UBI_MAX_RNVOL 32 + /* * UBI data type hint constants. * @@ -189,7 +201,7 @@ struct ubi_attach_req { int32_t ubi_num; int32_t mtd_num; int32_t vid_hdr_offset; - uint8_t padding[12]; + int8_t padding[12]; }; /** @@ -250,6 +262,48 @@ struct ubi_rsvol_req { int32_t vol_id; } __attribute__ ((packed)); +/** + * struct ubi_rnvol_req - volumes re-name request. + * @count: count of volumes to re-name + * @padding1: reserved for future, not used, has to be zeroed + * @vol_id: ID of the volume to re-name + * @name_len: name length + * @padding2: reserved for future, not used, has to be zeroed + * @name: new volume name + * + * UBI allows to re-name up to %32 volumes at one go. The count of volumes to + * re-name is specified in the @count field. The ID of the volumes to re-name + * and the new names are specified in the @vol_id and @name fields. + * + * The UBI volume re-name operation is atomic, which means that should power cut + * happen, the volumes will have either old name or new name. So the possible + * use-cases of this command is atomic upgrade. Indeed, to upgrade, say, volumes + * A and B one may create temporary volumes %A1 and %B1 with the new contents, + * then atomically re-name A1->A and B1->B, in which case old %A and %B will + * be removed. + * + * If it is not desirable to remove old A and B, the re-name request has to + * contain 4 entries: A1->A, A->A1, B1->B, B->B1, in which case old A1 and B1 + * become A and B, and old A and B will become A1 and B1. + * + * It is also OK to request: A1->A, A1->X, B1->B, B->Y, in which case old A1 + * and B1 become A and B, and old A and B become X and Y. + * + * In other words, in case of re-naming into an existing volume name, the + * existing volume is removed, unless it is re-named as well at the same + * re-name request. + */ +struct ubi_rnvol_req { + int32_t count; + int8_t padding1[12]; + struct { + int32_t vol_id; + int16_t name_len; + int8_t padding2[2]; + char name[UBI_MAX_VOLUME_NAME + 1]; + } ents[UBI_MAX_RNVOL]; +} __attribute__ ((packed)); + /** * struct ubi_leb_change_req - a data structure used in atomic logical * eraseblock change requests. @@ -261,8 +315,8 @@ struct ubi_rsvol_req { struct ubi_leb_change_req { int32_t lnum; int32_t bytes; - uint8_t dtype; - uint8_t padding[7]; + int8_t dtype; + int8_t padding[7]; } __attribute__ ((packed)); #endif /* __UBI_USER_H__ */ -- cgit v1.2.3-58-ga151 From 8c1e6ee10bd87d70faada065a8d1f70732c17382 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 12:20:23 +0300 Subject: UBI: rework scrubbing messages If bit-flips happen often, UBI prints to many messages. Lessen the amount by only printing the messages when the PEB has been scrubbed. Also, print torturing messages. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 8 +++++++- drivers/mtd/ubi/wl.c | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 27b9c2c2fc60..2bebb39d19b3 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -156,8 +156,12 @@ retry: /* * -EUCLEAN is reported if there was a bit-flip which * was corrected, so this is harmless. + * + * We do not report about it here unless debugging is + * enabled. A corresponding message will be printed + * later, when it is has been scrubbed. */ - ubi_msg("fixable bit-flip detected at PEB %d", pnum); + dbg_msg("fixable bit-flip detected at PEB %d", pnum); ubi_assert(len == read); return UBI_IO_BITFLIPS; } @@ -391,6 +395,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) { int err, i, patt_count; + ubi_msg("run torture test for PEB %d", pnum); patt_count = ARRAY_SIZE(patterns); ubi_assert(patt_count > 0); @@ -434,6 +439,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) } err = patt_count; + ubi_msg("PEB %d passed torture test, do not mark it a bad", pnum); out: mutex_unlock(&ubi->buf_mutex); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 761952ba125b..6821952bcdb8 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -873,6 +873,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, } ubi_free_vid_hdr(ubi, vid_hdr); + if (scrubbing && !protect) + ubi_msg("scrubbed PEB %d, data moved to PEB %d", + e1->pnum, e2->pnum); + spin_lock(&ubi->wl_lock); if (protect) prot_tree_add(ubi, e1, pe, protect); @@ -1231,7 +1235,7 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum) { struct ubi_wl_entry *e; - ubi_msg("schedule PEB %d for scrubbing", pnum); + dbg_msg("schedule PEB %d for scrubbing", pnum); retry: spin_lock(&ubi->wl_lock); -- cgit v1.2.3-58-ga151 From 4d88de4beb6f327dfc7c2221eab532dad5b2bb3e Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 12:42:14 +0300 Subject: UBI: bugfix - do not torture PEB needlessly This is probably a copy-paste bug - we torture the old PEB in the atomic LEB change function, but we should not do this. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/eba.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 613cd1e51648..e14208152c36 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -906,7 +906,7 @@ retry: } if (vol->eba_tbl[lnum] >= 0) { - err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1); + err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0); if (err) goto out_leb_unlock; } -- cgit v1.2.3-58-ga151 From 9c9ec147709e63e4e8ac6a037c6bb50688ff8e9c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 13:19:52 +0300 Subject: UBI: fix checkpatch.pl errors and warnings Just out or curiousity ran checkpatch.pl for whole UBI, and discovered there are quite a few of stylistic issues. Fix them. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 8 ++--- drivers/mtd/ubi/cdev.c | 4 +-- drivers/mtd/ubi/eba.c | 7 ++-- drivers/mtd/ubi/gluebi.c | 4 +-- drivers/mtd/ubi/io.c | 8 ++--- drivers/mtd/ubi/scan.c | 9 ++--- drivers/mtd/ubi/ubi.h | 3 +- drivers/mtd/ubi/upd.c | 8 +++-- drivers/mtd/ubi/vmt.c | 4 +-- drivers/mtd/ubi/vtbl.c | 12 +++---- drivers/mtd/ubi/wl.c | 92 +++++++++++++++++++++++------------------------- include/mtd/ubi-user.h | 16 ++++----- 12 files changed, 86 insertions(+), 89 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 4418a2369b56..535d9a8a6ba8 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -51,14 +51,13 @@ * @name: MTD device name or number string * @vid_hdr_offs: VID header offset */ -struct mtd_dev_param -{ +struct mtd_dev_param { char name[MTD_PARAM_LEN_MAX]; int vid_hdr_offs; }; /* Numbers of elements set in the @mtd_dev_param array */ -static int mtd_devs = 0; +static int mtd_devs; /* MTD devices specification parameters */ static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; @@ -781,7 +780,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) if (!ubi_devices[ubi_num]) break; if (ubi_num == UBI_MAX_DEVICES) { - dbg_err("only %d UBI devices may be created", UBI_MAX_DEVICES); + dbg_err("only %d UBI devices may be created", + UBI_MAX_DEVICES); return -ENFILE; } } else { diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index bc8199c6a9f5..03c759b4eeb5 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -39,9 +39,9 @@ #include #include #include +#include #include #include -#include #include #include "ubi.h" @@ -352,7 +352,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, } #else -#define vol_cdev_direct_write(file, buf, count, offp) -EPERM +#define vol_cdev_direct_write(file, buf, count, offp) (-EPERM) #endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */ static ssize_t vol_cdev_write(struct file *file, const char __user *buf, diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index e14208152c36..e04bcf1dff87 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -189,9 +189,7 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi, le->users += 1; spin_unlock(&ubi->ltree_lock); - if (le_free) - kfree(le_free); - + kfree(le_free); return le; } @@ -503,9 +501,8 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, struct ubi_vid_hdr *vid_hdr; vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); - if (!vid_hdr) { + if (!vid_hdr) return -ENOMEM; - } mutex_lock(&ubi->buf_mutex); diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 49f52dceea93..605812bb0b1a 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c @@ -249,8 +249,8 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr) if (err) goto out_err; - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); return 0; out_err: diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 2bebb39d19b3..a84f0db0a03a 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -167,8 +167,8 @@ retry: } if (read != len && retries++ < UBI_IO_RETRIES) { - dbg_io("error %d while reading %d bytes from PEB %d:%d, " - "read only %zd bytes, retry", + dbg_io("error %d while reading %d bytes from PEB %d:%d," + " read only %zd bytes, retry", err, len, pnum, offset, read); yield(); goto retry; @@ -705,8 +705,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, if (hdr_crc != crc) { if (verbose) { - ubi_warn("bad EC header CRC at PEB %d, calculated %#08x," - " read %#08x", pnum, crc, hdr_crc); + ubi_warn("bad EC header CRC at PEB %d, calculated " + "%#08x, read %#08x", pnum, crc, hdr_crc); ubi_dbg_dump_ec_hdr(ec_hdr); } return UBI_IO_BAD_EC_HDR; diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 40eca9ce5fab..0bb7488862d2 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -248,7 +248,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); if (seb->sqnum == 0 && sqnum2 == 0) { - long long abs, v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver); + long long abs; + long long v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver); /* * UBI constantly increases the logical eraseblock version @@ -752,7 +753,8 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, * This function returns a zero if the physical eraseblock was successfully * handled and a negative error code in case of failure. */ -static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum) +static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, + int pnum) { long long uninitialized_var(ec); int err, bitflips = 0, vol_id, ec_corr = 0; @@ -1301,8 +1303,7 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) if (err < 0) { kfree(buf); return err; - } - else if (err) + } else if (err) buf[pnum] = 1; } diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 274c67916b34..14a5596d2d9e 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -473,7 +473,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, const void __user *buf, int count); /* misc.c */ -int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length); +int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, + int length); int ubi_check_volume(struct ubi_device *ubi, int vol_id); void ubi_calculate_reserved(struct ubi_device *ubi); diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 1230a5e1b530..3b8beb8545c4 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -39,7 +39,7 @@ */ #include -#include +#include #include #include "ubi.h" @@ -246,7 +246,8 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, return 0; } - err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN); + err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, + UBI_UNKNOWN); } else { /* * When writing static volume, and this is the last logical @@ -418,7 +419,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, if (vol->upd_received == vol->upd_bytes) { int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size); - memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes); + memset(vol->upd_buf + vol->upd_bytes, 0xFF, + len - vol->upd_bytes); len = ubi_calc_data_len(ubi, vol->upd_buf, len); err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, vol->upd_buf, len, UBI_UNKNOWN); diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 4be4014c70df..852482d8b18f 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -253,7 +253,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) goto out_unlock; } - /* Calculate how many eraseblocks are requested */ + /* Calculate how many eraseblocks are requested */ vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; bytes = req->bytes; if (do_div(bytes, vol->usable_leb_size)) @@ -858,7 +858,7 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) if (alignment != vol->alignment || data_pad != vol->data_pad || upd_marker != vol->upd_marker || vol_type != vol->vol_type || - name_len!= vol->name_len || strncmp(name, vol->name, name_len)) { + name_len != vol->name_len || strncmp(name, vol->name, name_len)) { ubi_err("volume info is different"); goto fail; } diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 23c5376234b2..10c22257f601 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -461,7 +461,8 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, if (!leb_corrupted[0]) { /* LEB 0 is OK */ if (leb[1]) - leb_corrupted[1] = memcmp(leb[0], leb[1], ubi->vtbl_size); + leb_corrupted[1] = memcmp(leb[0], leb[1], + ubi->vtbl_size); if (leb_corrupted[1]) { ubi_warn("volume table copy #2 is corrupted"); err = create_vtbl(ubi, si, 1, leb[0]); @@ -859,11 +860,10 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) out_free: vfree(ubi->vtbl); - for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) - if (ubi->volumes[i]) { - kfree(ubi->volumes[i]); - ubi->volumes[i] = NULL; - } + for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { + kfree(ubi->volumes[i]); + ubi->volumes[i] = NULL; + } return err; } diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 6821952bcdb8..2a5d2a0e14ad 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -475,52 +475,47 @@ retry: } switch (dtype) { - case UBI_LONGTERM: - /* - * For long term data we pick a physical eraseblock - * with high erase counter. But the highest erase - * counter we can pick is bounded by the the lowest - * erase counter plus %WL_FREE_MAX_DIFF. - */ - e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF); - protect = LT_PROTECTION; - break; - case UBI_UNKNOWN: - /* - * For unknown data we pick a physical eraseblock with - * medium erase counter. But we by no means can pick a - * physical eraseblock with erase counter greater or - * equivalent than the lowest erase counter plus - * %WL_FREE_MAX_DIFF. - */ - first = rb_entry(rb_first(&ubi->free), - struct ubi_wl_entry, rb); - last = rb_entry(rb_last(&ubi->free), - struct ubi_wl_entry, rb); + case UBI_LONGTERM: + /* + * For long term data we pick a physical eraseblock with high + * erase counter. But the highest erase counter we can pick is + * bounded by the the lowest erase counter plus + * %WL_FREE_MAX_DIFF. + */ + e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF); + protect = LT_PROTECTION; + break; + case UBI_UNKNOWN: + /* + * For unknown data we pick a physical eraseblock with medium + * erase counter. But we by no means can pick a physical + * eraseblock with erase counter greater or equivalent than the + * lowest erase counter plus %WL_FREE_MAX_DIFF. + */ + first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb); + last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, rb); - if (last->ec - first->ec < WL_FREE_MAX_DIFF) - e = rb_entry(ubi->free.rb_node, - struct ubi_wl_entry, rb); - else { - medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2; - e = find_wl_entry(&ubi->free, medium_ec); - } - protect = U_PROTECTION; - break; - case UBI_SHORTTERM: - /* - * For short term data we pick a physical eraseblock - * with the lowest erase counter as we expect it will - * be erased soon. - */ - e = rb_entry(rb_first(&ubi->free), - struct ubi_wl_entry, rb); - protect = ST_PROTECTION; - break; - default: - protect = 0; - e = NULL; - BUG(); + if (last->ec - first->ec < WL_FREE_MAX_DIFF) + e = rb_entry(ubi->free.rb_node, + struct ubi_wl_entry, rb); + else { + medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2; + e = find_wl_entry(&ubi->free, medium_ec); + } + protect = U_PROTECTION; + break; + case UBI_SHORTTERM: + /* + * For short term data we pick a physical eraseblock with the + * lowest erase counter as we expect it will be erased soon. + */ + e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb); + protect = ST_PROTECTION; + break; + default: + protect = 0; + e = NULL; + BUG(); } /* @@ -584,7 +579,8 @@ found: * This function returns zero in case of success and a negative error code in * case of failure. */ -static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int torture) +static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, + int torture) { int err; struct ubi_ec_hdr *ec_hdr; @@ -1060,8 +1056,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, spin_unlock(&ubi->wl_lock); /* - * One more erase operation has happened, take care about protected - * physical eraseblocks. + * One more erase operation has happened, take care about + * protected physical eraseblocks. */ check_protection_over(ubi); diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index e8e57c3dfcdb..ccdc562e444e 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h @@ -188,14 +188,14 @@ enum { * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages. * * But in rare cases, if this optimizes things, the VID header may be placed to - * a different offset. For example, the boot-loader might do things faster if the - * VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As - * the boot-loader would not normally need to read EC headers (unless it needs - * UBI in RW mode), it might be faster to calculate ECC. This is weird example, - * but it real-life example. So, in this example, @vid_hdr_offer would be - * 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes - * aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page - * of the first page and add needed padding. + * a different offset. For example, the boot-loader might do things faster if + * the VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. + * As the boot-loader would not normally need to read EC headers (unless it + * needs UBI in RW mode), it might be faster to calculate ECC. This is weird + * example, but it real-life example. So, in this example, @vid_hdr_offer would + * be 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes + * aligned, which is OK, as UBI is clever enough to realize this is 4th + * sub-page of the first page and add needed padding. */ struct ubi_attach_req { int32_t ubi_num; -- cgit v1.2.3-58-ga151 From ebaaf1af3e9ef05c4fb7c61e4530c15e1ad10e3b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 13:34:32 +0300 Subject: UBI: fix kernel-doc errors and warnings No functional changes, just tweak comments to make kernel-doc work fine and stop complaining. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 8 +++----- drivers/mtd/ubi/io.c | 6 ++---- drivers/mtd/ubi/scan.c | 18 ++++++------------ drivers/mtd/ubi/ubi.h | 1 + drivers/mtd/ubi/upd.c | 2 ++ drivers/mtd/ubi/vmt.c | 2 +- drivers/mtd/ubi/vtbl.c | 8 +++----- drivers/mtd/ubi/wl.c | 13 +++++-------- 8 files changed, 23 insertions(+), 35 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 535d9a8a6ba8..eba760b3b8c7 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -159,8 +159,7 @@ void ubi_put_device(struct ubi_device *ubi) } /** - * ubi_get_by_major - get UBI device description object by character device - * major number. + * ubi_get_by_major - get UBI device by character device major number. * @major: major number * * This function is similar to 'ubi_get_device()', but it searches the device @@ -727,7 +726,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) /** * ubi_attach_mtd_dev - attach an MTD device. - * @mtd_dev: MTD device description object + * @mtd: MTD device description object * @ubi_num: number to assign to the new UBI device * @vid_hdr_offset: VID header offset * @@ -1095,8 +1094,7 @@ static void __exit ubi_exit(void) module_exit(ubi_exit); /** - * bytes_str_to_int - convert a string representing number of bytes to an - * integer. + * bytes_str_to_int - convert a number of bytes string into an integer. * @str: the string to convert * * This function returns positive resulting integer in case of success and a diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index a84f0db0a03a..2fb64be44f1b 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -1101,8 +1101,7 @@ fail: } /** - * paranoid_check_peb_ec_hdr - check that the erase counter header of a - * physical eraseblock is in-place and is all right. + * paranoid_check_peb_ec_hdr - check erase counter header. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * @@ -1180,8 +1179,7 @@ fail: } /** - * paranoid_check_peb_vid_hdr - check that the volume identifier header of a - * physical eraseblock is in-place and is all right. + * paranoid_check_peb_vid_hdr - check volume identifier header. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 0bb7488862d2..4dfbf27b0656 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -93,8 +93,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, } /** - * validate_vid_hdr - check that volume identifier header is correct and - * consistent. + * validate_vid_hdr - check volume identifier header. * @vid_hdr: the volume identifier header to check * @sv: information about the volume this logical eraseblock belongs to * @pnum: physical eraseblock number the VID header came from @@ -380,8 +379,7 @@ out_free_vidh: } /** - * ubi_scan_add_used - add information about a physical eraseblock to the - * scanning information. + * ubi_scan_add_used - add physical eraseblock to the scanning information. * @ubi: UBI device description object * @si: scanning information * @pnum: the physical eraseblock number @@ -555,8 +553,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, } /** - * ubi_scan_find_sv - find information about a particular volume in the - * scanning information. + * ubi_scan_find_sv - find volume in the scanning information. * @si: scanning information * @vol_id: the requested volume ID * @@ -585,8 +582,7 @@ struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si, } /** - * ubi_scan_find_seb - find information about a particular logical - * eraseblock in the volume scanning information. + * ubi_scan_find_seb - find LEB in the volume scanning information. * @sv: a pointer to the volume scanning information * @lnum: the requested logical eraseblock * @@ -744,8 +740,7 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, } /** - * process_eb - read UBI headers, check them and add corresponding data - * to the scanning information. + * process_eb - read, check UBI headers, and add them to scanning information. * @ubi: UBI device description object * @si: scanning information * @pnum: the physical eraseblock number @@ -1083,8 +1078,7 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID /** - * paranoid_check_si - check if the scanning information is correct and - * consistent. + * paranoid_check_si - check the scanning information. * @ubi: UBI device description object * @si: scanning information * diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 14a5596d2d9e..1c3fa18c26a7 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -313,6 +313,7 @@ struct ubi_wl_entry; * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works * fields * @move_mutex: serializes eraseblock moves + * @work_sem: sycnhronizes the WL worker with use tasks * @wl_scheduled: non-zero if the wear-leveling was scheduled * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any * physical eraseblock diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 3b8beb8545c4..8b89cc18ff0b 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -268,6 +268,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, /** * ubi_more_update_data - write more update data. + * @ubi: UBI device description object * @vol: volume description object * @buf: write data (user-space memory buffer) * @count: how much bytes to write @@ -385,6 +386,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, /** * ubi_more_leb_change_data - accept more data for atomic LEB change. + * @ubi: UBI device description object * @vol: volume description object * @buf: write data (user-space memory buffer) * @count: how much bytes to write diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 852482d8b18f..d40066833abb 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -608,7 +608,7 @@ out_free: /** * ubi_rename_volumes - re-name UBI volumes. * @ubi: UBI device description object - * @renam_list: list of &struct ubi_rename_entry objects + * @rename_list: list of &struct ubi_rename_entry objects * * This function re-names or removes volumes specified in the re-name list. * Returns zero in case of success and a negative error code in case of diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 10c22257f601..4e1c489a3bae 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -117,7 +117,7 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, /** * ubi_vtbl_rename_volumes - rename UBI volumes in the volume table. * @ubi: UBI device description object - * @renam_list: list of &struct ubi_rename_entry objects + * @rename_list: list of &struct ubi_rename_entry objects * * This function re-names multiple volumes specified in @req in the volume * table. Returns zero in case of success and a negative error code in case of @@ -166,8 +166,7 @@ int ubi_vtbl_rename_volumes(struct ubi_device *ubi, } /** - * vtbl_check - check if volume table is not corrupted and contains sensible - * data. + * vtbl_check - check if volume table is not corrupted and sensible. * @ubi: UBI device description object * @vtbl: volume table * @@ -780,8 +779,7 @@ static int check_scanning_info(const struct ubi_device *ubi, } /** - * ubi_read_volume_table - read volume table. - * information. + * ubi_read_volume_table - read the volume table. * @ubi: UBI device description object * @si: scanning information * diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 2a5d2a0e14ad..05d70937b543 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -632,8 +632,7 @@ out_free: } /** - * check_protection_over - check if it is time to stop protecting some - * physical eraseblocks. + * check_protection_over - check if it is time to stop protecting some PEBs. * @ubi: UBI device description object * * This function is called after each erase operation, when the absolute erase @@ -1601,8 +1600,7 @@ void ubi_wl_close(struct ubi_device *ubi) #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID /** - * paranoid_check_ec - make sure that the erase counter of a physical eraseblock - * is correct. + * paranoid_check_ec - make sure that the erase counter of a PEB is correct. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * @ec: the erase counter to check @@ -1643,13 +1641,12 @@ out_free: } /** - * paranoid_check_in_wl_tree - make sure that a wear-leveling entry is present - * in a WL RB-tree. + * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree. * @e: the wear-leveling entry to check * @root: the root of the tree * - * This function returns zero if @e is in the @root RB-tree and %1 if it - * is not. + * This function returns zero if @e is in the @root RB-tree and %1 if it is + * not. */ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root) -- cgit v1.2.3-58-ga151 From 9869cd801c107bbae91663c3f4edbb6b5715919f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 13:53:39 +0300 Subject: UBI: remove pre-sqnum images support Before UBI got into mainline, there was a slight flash format change - we did not have sequence number support, then added it. We have carried full support of those ancient images till this moment. Now the support is removed, well, not fully removed. Now UBI will support only _clean_ old images, which were cleanly detached last time (just before kernel upgrade). This is most likely the case. But we will not support unclean ancient images. Surprisingly, this allows us to remove a big chunk of legacy code. And the same should be true for downgrading: clean images should downgrade fine, but unclean ones will not. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/debug.c | 2 -- drivers/mtd/ubi/scan.c | 87 +++++++++++++-------------------------------- drivers/mtd/ubi/scan.h | 2 -- drivers/mtd/ubi/ubi-media.h | 17 ++++----- drivers/mtd/ubi/vtbl.c | 1 - 5 files changed, 30 insertions(+), 79 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 21e0d7d76a44..c0ed60e8ade9 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -65,7 +65,6 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) printk(KERN_DEBUG "\tcompat %d\n", (int)vid_hdr->compat); printk(KERN_DEBUG "\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id)); printk(KERN_DEBUG "\tlnum %d\n", be32_to_cpu(vid_hdr->lnum)); - printk(KERN_DEBUG "\tleb_ver %u\n", be32_to_cpu(vid_hdr->leb_ver)); printk(KERN_DEBUG "\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size)); printk(KERN_DEBUG "\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs)); printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad)); @@ -172,7 +171,6 @@ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type) printk(KERN_DEBUG "\tlnum %d\n", seb->lnum); printk(KERN_DEBUG "\tscrub %d\n", seb->scrub); printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum); - printk(KERN_DEBUG "\tleb_ver %u\n", seb->leb_ver); } } diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 4dfbf27b0656..967bb4406df9 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -246,46 +246,21 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, struct ubi_vid_hdr *vh = NULL; unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); - if (seb->sqnum == 0 && sqnum2 == 0) { - long long abs; - long long v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver); - + if (sqnum2 == seb->sqnum) { /* - * UBI constantly increases the logical eraseblock version - * number and it can overflow. Thus, we have to bear in mind - * that versions that are close to %0xFFFFFFFF are less then - * versions that are close to %0. - * - * The UBI WL sub-system guarantees that the number of pending - * tasks is not greater then %0x7FFFFFFF. So, if the difference - * between any two versions is greater or equivalent to - * %0x7FFFFFFF, there was an overflow and the logical - * eraseblock with lower version is actually newer then the one - * with higher version. - * - * FIXME: but this is anyway obsolete and will be removed at - * some point. + * This must be a really ancient UBI image which has been + * created before sequence numbers support has been added. At + * that times we used 32-bit LEB versions stored in logical + * eraseblocks. That was before UBI got into mainline. We do not + * support these images anymore. Well, those images will work + * still work, but only if no unclean reboots happened. */ - dbg_bld("using old crappy leb_ver stuff"); - - if (v1 == v2) { - ubi_err("PEB %d and PEB %d have the same version %lld", - seb->pnum, pnum, v1); - return -EINVAL; - } + ubi_err("unsupported on-flash UBI format\n"); + return -EINVAL; + } - abs = v1 - v2; - if (abs < 0) - abs = -abs; - - if (abs < 0x7FFFFFFF) - /* Non-overflow situation */ - second_is_newer = (v2 > v1); - else - second_is_newer = (v2 < v1); - } else - /* Obviously the LEB with lower sequence counter is older */ - second_is_newer = sqnum2 > seb->sqnum; + /* Obviously the LEB with lower sequence counter is older */ + second_is_newer = !!(sqnum2 > seb->sqnum); /* * Now we know which copy is newer. If the copy flag of the PEB with @@ -293,7 +268,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, * check data CRC. For the second PEB we already have the VID header, * for the first one - we'll need to re-read it from flash. * - * FIXME: this may be optimized so that we wouldn't read twice. + * Note: this may be optimized so that we wouldn't read twice. */ if (second_is_newer) { @@ -399,7 +374,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, int bitflips) { int err, vol_id, lnum; - uint32_t leb_ver; unsigned long long sqnum; struct ubi_scan_volume *sv; struct ubi_scan_leb *seb; @@ -408,10 +382,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, vol_id = be32_to_cpu(vid_hdr->vol_id); lnum = be32_to_cpu(vid_hdr->lnum); sqnum = be64_to_cpu(vid_hdr->sqnum); - leb_ver = be32_to_cpu(vid_hdr->leb_ver); - dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, ver %u, bitflips %d", - pnum, vol_id, lnum, ec, sqnum, leb_ver, bitflips); + dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d", + pnum, vol_id, lnum, ec, sqnum, bitflips); sv = add_volume(si, vol_id, pnum, vid_hdr); if (IS_ERR(sv) < 0) @@ -444,25 +417,20 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, */ dbg_bld("this LEB already exists: PEB %d, sqnum %llu, " - "LEB ver %u, EC %d", seb->pnum, seb->sqnum, - seb->leb_ver, seb->ec); - - /* - * Make sure that the logical eraseblocks have different - * versions. Otherwise the image is bad. - */ - if (seb->leb_ver == leb_ver && leb_ver != 0) { - ubi_err("two LEBs with same version %u", leb_ver); - ubi_dbg_dump_seb(seb, 0); - ubi_dbg_dump_vid_hdr(vid_hdr); - return -EINVAL; - } + "EC %d", seb->pnum, seb->sqnum, seb->ec); /* * Make sure that the logical eraseblocks have different * sequence numbers. Otherwise the image is bad. * - * FIXME: remove 'sqnum != 0' check when leb_ver is removed. + * However, if the sequence number is zero, we assume it must + * be an ancient UBI image from the era when UBI did not have + * sequence numbers. We still can attach these images, unless + * there is a need to distinguish between old and new + * eraseblocks, in which case we'll refuse the image in + * 'compare_lebs()'. In other words, we attach old clean + * images, but refuse attaching old images with duplicated + * logical eraseblocks because there was an unclean reboot. */ if (seb->sqnum == sqnum && sqnum != 0) { ubi_err("two LEBs with same sequence number %llu", @@ -502,7 +470,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, seb->pnum = pnum; seb->scrub = ((cmp_res & 2) || bitflips); seb->sqnum = sqnum; - seb->leb_ver = leb_ver; if (sv->highest_lnum == lnum) sv->last_data_size = @@ -539,7 +506,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, seb->lnum = lnum; seb->sqnum = sqnum; seb->scrub = bitflips; - seb->leb_ver = leb_ver; if (sv->highest_lnum <= lnum) { sv->highest_lnum = lnum; @@ -1263,11 +1229,6 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) ubi_err("bad data_pad %d", sv->data_pad); goto bad_vid_hdr; } - - if (seb->leb_ver != be32_to_cpu(vidh->leb_ver)) { - ubi_err("bad leb_ver %u", seb->leb_ver); - goto bad_vid_hdr; - } } if (!last_seb) diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 4e2e3cc0becd..61df208e2f20 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -34,7 +34,6 @@ * @u: unions RB-tree or @list links * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects * @u.list: link in one of the eraseblock lists - * @leb_ver: logical eraseblock version (obsolete) * * One object of this type is allocated for each physical eraseblock during * scanning. @@ -49,7 +48,6 @@ struct ubi_scan_leb { struct rb_node rb; struct list_head list; } u; - uint32_t leb_ver; }; /** diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index 26bb7af9787a..2ad940409053 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h @@ -168,16 +168,15 @@ struct ubi_ec_hdr { * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) * @vol_id: ID of this volume * @lnum: logical eraseblock number - * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be - * removed, kept only for not breaking older UBI users) + * @padding1: reserved for future, zeroes * @data_size: how many bytes of data this logical eraseblock contains * @used_ebs: total number of used logical eraseblocks in this volume * @data_pad: how many bytes at the end of this physical eraseblock are not * used * @data_crc: CRC checksum of the data stored in this logical eraseblock - * @padding1: reserved for future, zeroes - * @sqnum: sequence number * @padding2: reserved for future, zeroes + * @sqnum: sequence number + * @padding3: reserved for future, zeroes * @hdr_crc: volume identifier header CRC checksum * * The @sqnum is the value of the global sequence counter at the time when this @@ -225,10 +224,6 @@ struct ubi_ec_hdr { * checksum is correct, this physical eraseblock is selected (P1). Otherwise * the older one (P) is selected. * - * Note, there is an obsolete @leb_ver field which was used instead of @sqnum - * in the past. But it is not used anymore and we keep it in order to be able - * to deal with old UBI images. It will be removed at some point. - * * There are 2 sorts of volumes in UBI: user volumes and internal volumes. * Internal volumes are not seen from outside and are used for various internal * UBI purposes. In this implementation there is only one internal volume - the @@ -278,14 +273,14 @@ struct ubi_vid_hdr { __u8 compat; __be32 vol_id; __be32 lnum; - __be32 leb_ver; /* obsolete, to be removed, don't use */ + __u8 padding1[4]; __be32 data_size; __be32 used_ebs; __be32 data_pad; __be32 data_crc; - __u8 padding1[4]; + __u8 padding2[4]; __be64 sqnum; - __u8 padding2[12]; + __u8 padding3[12]; __be32 hdr_crc; } __attribute__ ((packed)); diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 4e1c489a3bae..217d0e111b2a 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -338,7 +338,6 @@ retry: vid_hdr->data_pad = cpu_to_be32(0); vid_hdr->lnum = cpu_to_be32(copy); vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum); - vid_hdr->leb_ver = cpu_to_be32(old_seb ? old_seb->leb_ver + 1: 0); /* The EC header is already there, write the VID header */ err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr); -- cgit v1.2.3-58-ga151 From eeb16e87b6747c9a4f5769f33467c9d173e9f5ee Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 23 Jul 2008 15:51:46 +0300 Subject: UBI: fix gcc warning Fix the following warning: drivers/mtd/ubi/vmt.c: In function 'ubi_rename_volumes': drivers/mtd/ubi/vmt.c:642: warning: statement with no effect Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/vmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index d40066833abb..3531ca9a1e24 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -639,7 +639,7 @@ int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list) } if (!err) - paranoid_check_volumes(ubi); + err = paranoid_check_volumes(ubi); return err; } -- cgit v1.2.3-58-ga151 From d37e6bf68fc1eb34a4ad21d9ae8890ed37ea80e7 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 24 Jul 2008 18:28:11 +0300 Subject: UBI: always start the background thread This fix only affects UBI debugging. If the the background thread is disabled for debugging purposes, start it anyway, because otherwise we see tonns of kernel debugging complaints like this: INFO: task ubi_bgt0d:26857 blocked for more than 120 seconds. "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. ubi_bgt0d D dd37bf94 0 26857 2 dd37bfcc 00000086 f8e17cea dd37bf94 00000046 00000000 00000000 f5c62430 f5c62430 f5c62590 c2a09c80 f6cbd498 dd8e9cbc 00000296 dd37bfb0 00000296 dd8e9cb8 dd8e9cbc dd37bfcc c0119774 00000000 00000000 c0132e89 f6961560 Call Trace: [] ? ubi_thread+0x0/0x127 [ubi] [] ? complete+0x43/0x4b [] ? kthread+0x0/0x5b [] ? ubi_thread+0x0/0x127 [ubi] [] kthread+0x25/0x5b [] ? kthread+0x0/0x5b [] kernel_thread_helper+0x7/0x14 ======================= So start it, and go sleep inside it, instead of creating it and never start. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index eba760b3b8c7..c7630a228310 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -870,11 +870,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ubi->beb_rsvd_pebs); ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); - /* Enable the background thread */ - if (!DBG_DISABLE_BGT) { + if (!DBG_DISABLE_BGT) ubi->thread_enabled = 1; - wake_up_process(ubi->bgt_thread); - } + wake_up_process(ubi->bgt_thread); ubi_devices[ubi_num] = ubi; return ubi_num; -- cgit v1.2.3-58-ga151