Initial commit
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Build Kernel / Build all affected Kernels (push) Has been cancelled
				
			
		
			
				
	
				Build all core packages / Build all core packages for selected target (push) Has been cancelled
				
			
		
			
				
	
				Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
				
			
		
			
				
	
				Build Toolchains / Build Toolchains for each target (push) Has been cancelled
				
			
		
			
				
	
				Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
				
			
		
			
				
	
				Coverity scan build / Coverity x86/64 build (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Build Kernel / Build all affected Kernels (push) Has been cancelled
				
			Build all core packages / Build all core packages for selected target (push) Has been cancelled
				
			Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
				
			Build Toolchains / Build Toolchains for each target (push) Has been cancelled
				
			Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
				
			Coverity scan build / Coverity x86/64 build (push) Has been cancelled
				
			This commit is contained in:
		
							
								
								
									
										328
									
								
								target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,328 @@ | ||||
| From 39717277d5c87bdb183cf2f258957b44ba99b4df Mon Sep 17 00:00:00 2001 | ||||
| From: OpenWrt community <openwrt-devel@lists.openwrt.org> | ||||
| Date: Wed, 13 Jul 2022 11:47:35 +0200 | ||||
| Subject: [PATCH] mtd: mtdsplit support | ||||
|  | ||||
| --- | ||||
|  drivers/mtd/Kconfig            |  19 ++++ | ||||
|  drivers/mtd/Makefile           |   2 + | ||||
|  drivers/mtd/mtdpart.c          | 169 ++++++++++++++++++++++++++++----- | ||||
|  include/linux/mtd/mtd.h        |  25 +++++ | ||||
|  include/linux/mtd/partitions.h |   7 ++ | ||||
|  5 files changed, 197 insertions(+), 25 deletions(-) | ||||
|  | ||||
| --- a/drivers/mtd/Kconfig | ||||
| +++ b/drivers/mtd/Kconfig | ||||
| @@ -12,6 +12,25 @@ menuconfig MTD | ||||
|   | ||||
|  if MTD | ||||
|   | ||||
| +menu "OpenWrt specific MTD options" | ||||
| + | ||||
| +config MTD_ROOTFS_ROOT_DEV | ||||
| +	bool "Automatically set 'rootfs' partition to be root filesystem" | ||||
| +	default y | ||||
| + | ||||
| +config MTD_SPLIT_FIRMWARE | ||||
| +	bool "Automatically split firmware partition for kernel+rootfs" | ||||
| +	default y | ||||
| + | ||||
| +config MTD_SPLIT_FIRMWARE_NAME | ||||
| +	string "Firmware partition name" | ||||
| +	depends on MTD_SPLIT_FIRMWARE | ||||
| +	default "firmware" | ||||
| + | ||||
| +source "drivers/mtd/mtdsplit/Kconfig" | ||||
| + | ||||
| +endmenu | ||||
| + | ||||
|  config MTD_TESTS | ||||
|  	tristate "MTD tests support (DANGEROUS)" | ||||
|  	depends on m | ||||
| --- a/drivers/mtd/Makefile | ||||
| +++ b/drivers/mtd/Makefile | ||||
| @@ -9,6 +9,8 @@ mtd-y				:= mtdcore.o mtdsuper.o mtdconc | ||||
|   | ||||
|  obj-y				+= parsers/ | ||||
|   | ||||
| +obj-$(CONFIG_MTD_SPLIT)		+= mtdsplit/ | ||||
| + | ||||
|  # 'Users' - code which presents functionality to userspace. | ||||
|  obj-$(CONFIG_MTD_BLKDEVS)	+= mtd_blkdevs.o | ||||
|  obj-$(CONFIG_MTD_BLOCK)		+= mtdblock.o | ||||
| --- a/drivers/mtd/mtdpart.c | ||||
| +++ b/drivers/mtd/mtdpart.c | ||||
| @@ -15,11 +15,13 @@ | ||||
|  #include <linux/kmod.h> | ||||
|  #include <linux/mtd/mtd.h> | ||||
|  #include <linux/mtd/partitions.h> | ||||
| +#include <linux/magic.h> | ||||
|  #include <linux/err.h> | ||||
|  #include <linux/of.h> | ||||
|  #include <linux/of_platform.h> | ||||
|   | ||||
|  #include "mtdcore.h" | ||||
| +#include "mtdsplit/mtdsplit.h" | ||||
|   | ||||
|  /* | ||||
|   * MTD methods which simply translate the effective address and pass through | ||||
| @@ -242,6 +244,147 @@ static int mtd_add_partition_attrs(struc | ||||
|  	return ret; | ||||
|  } | ||||
|   | ||||
| +static DEFINE_SPINLOCK(part_parser_lock); | ||||
| +static LIST_HEAD(part_parsers); | ||||
| + | ||||
| +static struct mtd_part_parser *mtd_part_parser_get(const char *name) | ||||
| +{ | ||||
| +	struct mtd_part_parser *p, *ret = NULL; | ||||
| + | ||||
| +	spin_lock(&part_parser_lock); | ||||
| + | ||||
| +	list_for_each_entry(p, &part_parsers, list) | ||||
| +		if (!strcmp(p->name, name) && try_module_get(p->owner)) { | ||||
| +			ret = p; | ||||
| +			break; | ||||
| +		} | ||||
| + | ||||
| +	spin_unlock(&part_parser_lock); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static inline void mtd_part_parser_put(const struct mtd_part_parser *p) | ||||
| +{ | ||||
| +	module_put(p->owner); | ||||
| +} | ||||
| + | ||||
| +static struct mtd_part_parser * | ||||
| +get_partition_parser_by_type(enum mtd_parser_type type, | ||||
| +			     struct mtd_part_parser *start) | ||||
| +{ | ||||
| +	struct mtd_part_parser *p, *ret = NULL; | ||||
| + | ||||
| +	spin_lock(&part_parser_lock); | ||||
| + | ||||
| +	p = list_prepare_entry(start, &part_parsers, list); | ||||
| +	if (start) | ||||
| +		mtd_part_parser_put(start); | ||||
| + | ||||
| +	list_for_each_entry_continue(p, &part_parsers, list) { | ||||
| +		if (p->type == type && try_module_get(p->owner)) { | ||||
| +			ret = p; | ||||
| +			break; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	spin_unlock(&part_parser_lock); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int parse_mtd_partitions_by_type(struct mtd_info *master, | ||||
| +					enum mtd_parser_type type, | ||||
| +					const struct mtd_partition **pparts, | ||||
| +					struct mtd_part_parser_data *data) | ||||
| +{ | ||||
| +	struct mtd_part_parser *prev = NULL; | ||||
| +	int ret = 0; | ||||
| + | ||||
| +	while (1) { | ||||
| +		struct mtd_part_parser *parser; | ||||
| + | ||||
| +		parser = get_partition_parser_by_type(type, prev); | ||||
| +		if (!parser) | ||||
| +			break; | ||||
| + | ||||
| +		ret = (*parser->parse_fn)(master, pparts, data); | ||||
| + | ||||
| +		if (ret > 0) { | ||||
| +			mtd_part_parser_put(parser); | ||||
| +			printk(KERN_NOTICE | ||||
| +			       "%d %s partitions found on MTD device %s\n", | ||||
| +			       ret, parser->name, master->name); | ||||
| +			break; | ||||
| +		} | ||||
| + | ||||
| +		prev = parser; | ||||
| +	} | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +run_parsers_by_type(struct mtd_info *child, enum mtd_parser_type type) | ||||
| +{ | ||||
| +	struct mtd_partition *parts; | ||||
| +	int nr_parts; | ||||
| +	int i; | ||||
| + | ||||
| +	nr_parts = parse_mtd_partitions_by_type(child, type, (const struct mtd_partition **)&parts, | ||||
| +						NULL); | ||||
| +	if (nr_parts <= 0) | ||||
| +		return nr_parts; | ||||
| + | ||||
| +	if (WARN_ON(!parts)) | ||||
| +		return 0; | ||||
| + | ||||
| +	for (i = 0; i < nr_parts; i++) { | ||||
| +		/* adjust partition offsets */ | ||||
| +		parts[i].offset += child->part.offset; | ||||
| + | ||||
| +		mtd_add_partition(child->parent, | ||||
| +				  parts[i].name, | ||||
| +				  parts[i].offset, | ||||
| +				  parts[i].size); | ||||
| +	} | ||||
| + | ||||
| +	kfree(parts); | ||||
| + | ||||
| +	return nr_parts; | ||||
| +} | ||||
| + | ||||
| +#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME | ||||
| +#define SPLIT_FIRMWARE_NAME	CONFIG_MTD_SPLIT_FIRMWARE_NAME | ||||
| +#else | ||||
| +#define SPLIT_FIRMWARE_NAME	"unused" | ||||
| +#endif | ||||
| + | ||||
| +static void split_firmware(struct mtd_info *master, struct mtd_info *part) | ||||
| +{ | ||||
| +	run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); | ||||
| +} | ||||
| + | ||||
| +static void mtd_partition_split(struct mtd_info *master, struct mtd_info *part) | ||||
| +{ | ||||
| +	static int rootfs_found = 0; | ||||
| + | ||||
| +	if (rootfs_found) | ||||
| +		return; | ||||
| + | ||||
| +	if (of_find_property(mtd_get_of_node(part), "linux,rootfs", NULL) || | ||||
| +	    !strcmp(part->name, "rootfs")) { | ||||
| +		run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); | ||||
| + | ||||
| +		rootfs_found = 1; | ||||
| +	} | ||||
| + | ||||
| +	if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) && | ||||
| +	    !strcmp(part->name, SPLIT_FIRMWARE_NAME) && | ||||
| +	    !of_find_property(mtd_get_of_node(part), "compatible", NULL)) | ||||
| +		split_firmware(master, part); | ||||
| +} | ||||
| + | ||||
|  int mtd_add_partition(struct mtd_info *parent, const char *name, | ||||
|  		      long long offset, long long length) | ||||
|  { | ||||
| @@ -280,6 +423,7 @@ int mtd_add_partition(struct mtd_info *p | ||||
|  	if (ret) | ||||
|  		goto err_remove_part; | ||||
|   | ||||
| +	mtd_partition_split(parent, child); | ||||
|  	mtd_add_partition_attrs(child); | ||||
|   | ||||
|  	return 0; | ||||
| @@ -423,6 +567,7 @@ int add_mtd_partitions(struct mtd_info * | ||||
|  			goto err_del_partitions; | ||||
|  		} | ||||
|   | ||||
| +		mtd_partition_split(master, child); | ||||
|  		mtd_add_partition_attrs(child); | ||||
|   | ||||
|  		/* Look for subpartitions */ | ||||
| @@ -439,31 +584,6 @@ err_del_partitions: | ||||
|  	return ret; | ||||
|  } | ||||
|   | ||||
| -static DEFINE_SPINLOCK(part_parser_lock); | ||||
| -static LIST_HEAD(part_parsers); | ||||
| - | ||||
| -static struct mtd_part_parser *mtd_part_parser_get(const char *name) | ||||
| -{ | ||||
| -	struct mtd_part_parser *p, *ret = NULL; | ||||
| - | ||||
| -	spin_lock(&part_parser_lock); | ||||
| - | ||||
| -	list_for_each_entry(p, &part_parsers, list) | ||||
| -		if (!strcmp(p->name, name) && try_module_get(p->owner)) { | ||||
| -			ret = p; | ||||
| -			break; | ||||
| -		} | ||||
| - | ||||
| -	spin_unlock(&part_parser_lock); | ||||
| - | ||||
| -	return ret; | ||||
| -} | ||||
| - | ||||
| -static inline void mtd_part_parser_put(const struct mtd_part_parser *p) | ||||
| -{ | ||||
| -	module_put(p->owner); | ||||
| -} | ||||
| - | ||||
|  /* | ||||
|   * Many partition parsers just expected the core to kfree() all their data in | ||||
|   * one chunk. Do that by default. | ||||
| --- a/include/linux/mtd/mtd.h | ||||
| +++ b/include/linux/mtd/mtd.h | ||||
| @@ -615,6 +615,24 @@ static inline void mtd_align_erase_req(s | ||||
|  		req->len += mtd->erasesize - mod; | ||||
|  } | ||||
|   | ||||
| +static inline uint64_t mtd_roundup_to_eb(uint64_t sz, struct mtd_info *mtd) | ||||
| +{ | ||||
| +	if (mtd_mod_by_eb(sz, mtd) == 0) | ||||
| +		return sz; | ||||
| + | ||||
| +	/* Round up to next erase block */ | ||||
| +	return (mtd_div_by_eb(sz, mtd) + 1) * mtd->erasesize; | ||||
| +} | ||||
| + | ||||
| +static inline uint64_t mtd_rounddown_to_eb(uint64_t sz, struct mtd_info *mtd) | ||||
| +{ | ||||
| +	if (mtd_mod_by_eb(sz, mtd) == 0) | ||||
| +		return sz; | ||||
| + | ||||
| +	/* Round down to the start of the current erase block */ | ||||
| +	return (mtd_div_by_eb(sz, mtd)) * mtd->erasesize; | ||||
| +} | ||||
| + | ||||
|  static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) | ||||
|  { | ||||
|  	if (mtd->writesize_shift) | ||||
| @@ -688,6 +706,13 @@ extern struct mtd_info *of_get_mtd_devic | ||||
|  extern struct mtd_info *get_mtd_device_nm(const char *name); | ||||
|  extern void put_mtd_device(struct mtd_info *mtd); | ||||
|   | ||||
| +static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd) | ||||
| +{ | ||||
| +	if (!mtd_is_partition(mtd)) | ||||
| +		return 0; | ||||
| + | ||||
| +	return mtd->part.offset; | ||||
| +} | ||||
|   | ||||
|  struct mtd_notifier { | ||||
|  	void (*add)(struct mtd_info *mtd); | ||||
| --- a/include/linux/mtd/partitions.h | ||||
| +++ b/include/linux/mtd/partitions.h | ||||
| @@ -75,6 +75,12 @@ struct mtd_part_parser_data { | ||||
|   * Functions dealing with the various ways of partitioning the space | ||||
|   */ | ||||
|   | ||||
| +enum mtd_parser_type { | ||||
| +	MTD_PARSER_TYPE_DEVICE = 0, | ||||
| +	MTD_PARSER_TYPE_ROOTFS, | ||||
| +	MTD_PARSER_TYPE_FIRMWARE, | ||||
| +}; | ||||
| + | ||||
|  struct mtd_part_parser { | ||||
|  	struct list_head list; | ||||
|  	struct module *owner; | ||||
| @@ -83,6 +89,7 @@ struct mtd_part_parser { | ||||
|  	int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, | ||||
|  			struct mtd_part_parser_data *); | ||||
|  	void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); | ||||
| +	enum mtd_parser_type type; | ||||
|  }; | ||||
|   | ||||
|  /* Container for passing around a set of parsed partitions */ | ||||
		Reference in New Issue
	
	Block a user
	 domenico
					domenico