diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
index 8446765878304e0ee543cbf3d9bb4a0eb6a4ecc4..4c358924e440cfc636dbc1f8f9195f90718eb3fc 100644
--- a/common/cmd_ubi.c
+++ b/common/cmd_ubi.c
@@ -31,6 +31,7 @@
 /* Private own data */
 static struct ubi_device *ubi;
 static char buffer[80];
+static int ubi_initialized;
 
 struct selected_dev {
 	char dev_name[32];	/* NAND/OneNAND etc */
@@ -428,6 +429,8 @@ static int ubi_dev_scan(struct mtd_info *info, char *ubidev)
 		return err;
 	}
 
+	ubi_initialized = 1;
+
 	return 0;
 }
 
@@ -463,6 +466,14 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 		/* todo: get dev number for NAND... */
 		ubi_dev.nr = 0;
 
+		/*
+		 * Call ubi_exit() before re-initializing the UBI subsystem
+		 */
+		if (ubi_initialized) {
+			ubi_exit();
+			del_mtd_partitions(ubi_dev.mtd_info);
+		}
+
 		/*
 		 * Check for nand|onenand selection
 		 */
@@ -497,6 +508,7 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 		err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name);
 		if (err) {
 			printf("UBI init error %d\n", err);
+			ubi_dev.type = DEV_TYPE_NONE;
 			return err;
 		}
 
@@ -535,7 +547,7 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 		}
 		/* E.g., create volume size */
 		if (argc == 4) {
-			addr = simple_strtoul(argv[3], NULL, 16);
+			size = simple_strtoul(argv[3], NULL, 16);
 			argc--;
 		}
 		/* Use maximum available size */
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 9a3bf6f39d236107b19afb68bc0c8822aa08aa55..f010f5e3ac5cdf1363093608eab9e61c4e3ccd40 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -20,7 +20,7 @@
 #include <linux/mtd/compat.h>
 
 /* Our partition linked list */
-static LIST_HEAD(mtd_partitions);
+struct list_head mtd_partitions;
 
 /* Our partition node structure */
 struct mtd_part {
@@ -349,6 +349,14 @@ int add_mtd_partitions(struct mtd_info *master,
 	u_int32_t cur_offset = 0;
 	int i;
 
+	/*
+	 * Need to init the list here, since LIST_INIT() does not
+	 * work on platforms where relocation has problems (like MIPS
+	 * & PPC).
+	 */
+	if (mtd_partitions.next == NULL)
+		INIT_LIST_HEAD(&mtd_partitions);
+
 	printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 
 	for (i = 0; i < nbparts; i++) {
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 17cabb2ae9952f5be88c467d3feaf5c81f1a7b78..f4b01a9ded249adb84d6387e72633d53b1095a4a 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -784,19 +784,20 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	if (err)
 		goto out_free;
 
+	err = -ENOMEM;
 	ubi->peb_buf1 = vmalloc(ubi->peb_size);
 	if (!ubi->peb_buf1)
 		goto out_free;
 
 	ubi->peb_buf2 = vmalloc(ubi->peb_size);
 	if (!ubi->peb_buf2)
-		 goto out_free;
+		goto out_free;
 
 #ifdef CONFIG_MTD_UBI_DEBUG
 	mutex_init(&ubi->dbg_buf_mutex);
 	ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
 	if (!ubi->dbg_peb_buf)
-		 goto out_free;
+		goto out_free;
 #endif
 
 	err = attach_by_scanning(ubi);
@@ -1059,6 +1060,7 @@ void __exit ubi_exit(void)
 	misc_deregister(&ubi_ctrl_cdev);
 	class_remove_file(ubi_class, &ubi_version);
 	class_destroy(ubi_class);
+	mtd_devs = 0;
 }
 module_exit(ubi_exit);
 
diff --git a/include/ubi_uboot.h b/include/ubi_uboot.h
index 295f2c0ffc895387b09eb7c3ec6fbcbfb29f1d41..095dfc1b206a0e56f90fef961c52ae9cbdc14a6a 100644
--- a/include/ubi_uboot.h
+++ b/include/ubi_uboot.h
@@ -211,6 +211,7 @@ static inline long IS_ERR(const void *ptr)
 /* functions */
 extern int ubi_mtd_param_parse(const char *val, struct kernel_param *kp);
 extern int ubi_init(void);
+extern void ubi_exit(void);
 
 extern struct ubi_device *ubi_devices[];