xref: /openbmc/linux/drivers/mtd/ubi/misc.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2801c135cSArtem B. Bityutskiy /*
3801c135cSArtem B. Bityutskiy  * Copyright (c) International Business Machines Corp., 2006
4801c135cSArtem B. Bityutskiy  *
5801c135cSArtem B. Bityutskiy  * Author: Artem Bityutskiy (Битюцкий Артём)
6801c135cSArtem B. Bityutskiy  */
7801c135cSArtem B. Bityutskiy 
8801c135cSArtem B. Bityutskiy /* Here we keep miscellaneous functions which are used all over the UBI code */
9801c135cSArtem B. Bityutskiy 
10801c135cSArtem B. Bityutskiy #include "ubi.h"
11801c135cSArtem B. Bityutskiy 
12801c135cSArtem B. Bityutskiy /**
13*0b3bc49cSRandy Dunlap  * ubi_calc_data_len - calculate how much real data is stored in a buffer.
14801c135cSArtem B. Bityutskiy  * @ubi: UBI device description object
15801c135cSArtem B. Bityutskiy  * @buf: a buffer with the contents of the physical eraseblock
16801c135cSArtem B. Bityutskiy  * @length: the buffer length
17801c135cSArtem B. Bityutskiy  *
18801c135cSArtem B. Bityutskiy  * This function calculates how much "real data" is stored in @buf and returnes
19801c135cSArtem B. Bityutskiy  * the length. Continuous 0xFF bytes at the end of the buffer are not
20801c135cSArtem B. Bityutskiy  * considered as "real data".
21801c135cSArtem B. Bityutskiy  */
ubi_calc_data_len(const struct ubi_device * ubi,const void * buf,int length)22801c135cSArtem B. Bityutskiy int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
23801c135cSArtem B. Bityutskiy 		      int length)
24801c135cSArtem B. Bityutskiy {
25801c135cSArtem B. Bityutskiy 	int i;
26801c135cSArtem B. Bityutskiy 
27cadb40ccSKyungmin Park 	ubi_assert(!(length & (ubi->min_io_size - 1)));
28801c135cSArtem B. Bityutskiy 
29801c135cSArtem B. Bityutskiy 	for (i = length - 1; i >= 0; i--)
30801c135cSArtem B. Bityutskiy 		if (((const uint8_t *)buf)[i] != 0xFF)
31801c135cSArtem B. Bityutskiy 			break;
32801c135cSArtem B. Bityutskiy 
33801c135cSArtem B. Bityutskiy 	/* The resulting length must be aligned to the minimum flash I/O size */
34801c135cSArtem B. Bityutskiy 	length = ALIGN(i + 1, ubi->min_io_size);
35801c135cSArtem B. Bityutskiy 	return length;
36801c135cSArtem B. Bityutskiy }
37801c135cSArtem B. Bityutskiy 
38801c135cSArtem B. Bityutskiy /**
39801c135cSArtem B. Bityutskiy  * ubi_check_volume - check the contents of a static volume.
40801c135cSArtem B. Bityutskiy  * @ubi: UBI device description object
41801c135cSArtem B. Bityutskiy  * @vol_id: ID of the volume to check
42801c135cSArtem B. Bityutskiy  *
43801c135cSArtem B. Bityutskiy  * This function checks if static volume @vol_id is corrupted by fully reading
44801c135cSArtem B. Bityutskiy  * it and checking data CRC. This function returns %0 if the volume is not
45801c135cSArtem B. Bityutskiy  * corrupted, %1 if it is corrupted and a negative error code in case of
46801c135cSArtem B. Bityutskiy  * failure. Dynamic volumes are not checked and zero is returned immediately.
47801c135cSArtem B. Bityutskiy  */
ubi_check_volume(struct ubi_device * ubi,int vol_id)48801c135cSArtem B. Bityutskiy int ubi_check_volume(struct ubi_device *ubi, int vol_id)
49801c135cSArtem B. Bityutskiy {
50801c135cSArtem B. Bityutskiy 	void *buf;
51801c135cSArtem B. Bityutskiy 	int err = 0, i;
52801c135cSArtem B. Bityutskiy 	struct ubi_volume *vol = ubi->volumes[vol_id];
53801c135cSArtem B. Bityutskiy 
54801c135cSArtem B. Bityutskiy 	if (vol->vol_type != UBI_STATIC_VOLUME)
55801c135cSArtem B. Bityutskiy 		return 0;
56801c135cSArtem B. Bityutskiy 
5792ad8f37SArtem Bityutskiy 	buf = vmalloc(vol->usable_leb_size);
58801c135cSArtem B. Bityutskiy 	if (!buf)
59801c135cSArtem B. Bityutskiy 		return -ENOMEM;
60801c135cSArtem B. Bityutskiy 
61801c135cSArtem B. Bityutskiy 	for (i = 0; i < vol->used_ebs; i++) {
62801c135cSArtem B. Bityutskiy 		int size;
63801c135cSArtem B. Bityutskiy 
649aa272b4Shujianyang 		cond_resched();
659aa272b4Shujianyang 
66801c135cSArtem B. Bityutskiy 		if (i == vol->used_ebs - 1)
67801c135cSArtem B. Bityutskiy 			size = vol->last_eb_bytes;
68801c135cSArtem B. Bityutskiy 		else
69801c135cSArtem B. Bityutskiy 			size = vol->usable_leb_size;
70801c135cSArtem B. Bityutskiy 
7189b96b69SArtem Bityutskiy 		err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1);
72801c135cSArtem B. Bityutskiy 		if (err) {
73d57f4054SBrian Norris 			if (mtd_is_eccerr(err))
74801c135cSArtem B. Bityutskiy 				err = 1;
75801c135cSArtem B. Bityutskiy 			break;
76801c135cSArtem B. Bityutskiy 		}
77801c135cSArtem B. Bityutskiy 	}
78801c135cSArtem B. Bityutskiy 
7992ad8f37SArtem Bityutskiy 	vfree(buf);
80801c135cSArtem B. Bityutskiy 	return err;
81801c135cSArtem B. Bityutskiy }
82801c135cSArtem B. Bityutskiy 
83801c135cSArtem B. Bityutskiy /**
8487e773c9SShmulik Ladkani  * ubi_update_reserved - update bad eraseblock handling accounting data.
8587e773c9SShmulik Ladkani  * @ubi: UBI device description object
8687e773c9SShmulik Ladkani  *
8787e773c9SShmulik Ladkani  * This function calculates the gap between current number of PEBs reserved for
8887e773c9SShmulik Ladkani  * bad eraseblock handling and the required level of PEBs that must be
8987e773c9SShmulik Ladkani  * reserved, and if necessary, reserves more PEBs to fill that gap, according
9087e773c9SShmulik Ladkani  * to availability. Should be called with ubi->volumes_lock held.
9187e773c9SShmulik Ladkani  */
ubi_update_reserved(struct ubi_device * ubi)9287e773c9SShmulik Ladkani void ubi_update_reserved(struct ubi_device *ubi)
9387e773c9SShmulik Ladkani {
9487e773c9SShmulik Ladkani 	int need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
9587e773c9SShmulik Ladkani 
9687e773c9SShmulik Ladkani 	if (need <= 0 || ubi->avail_pebs == 0)
9787e773c9SShmulik Ladkani 		return;
9887e773c9SShmulik Ladkani 
9987e773c9SShmulik Ladkani 	need = min_t(int, need, ubi->avail_pebs);
10087e773c9SShmulik Ladkani 	ubi->avail_pebs -= need;
10187e773c9SShmulik Ladkani 	ubi->rsvd_pebs += need;
10287e773c9SShmulik Ladkani 	ubi->beb_rsvd_pebs += need;
10332608703STanya Brokhman 	ubi_msg(ubi, "reserved more %d PEBs for bad PEB handling", need);
10487e773c9SShmulik Ladkani }
10587e773c9SShmulik Ladkani 
10687e773c9SShmulik Ladkani /**
1075c669a5bSShmulik Ladkani  * ubi_calculate_reserved - calculate how many PEBs must be reserved for bad
108801c135cSArtem B. Bityutskiy  * eraseblock handling.
109801c135cSArtem B. Bityutskiy  * @ubi: UBI device description object
110801c135cSArtem B. Bityutskiy  */
ubi_calculate_reserved(struct ubi_device * ubi)111801c135cSArtem B. Bityutskiy void ubi_calculate_reserved(struct ubi_device *ubi)
112801c135cSArtem B. Bityutskiy {
11337f758a0SShmulik Ladkani 	/*
11437f758a0SShmulik Ladkani 	 * Calculate the actual number of PEBs currently needed to be reserved
11537f758a0SShmulik Ladkani 	 * for future bad eraseblock handling.
11637f758a0SShmulik Ladkani 	 */
11737f758a0SShmulik Ladkani 	ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count;
11837f758a0SShmulik Ladkani 	if (ubi->beb_rsvd_level < 0) {
11937f758a0SShmulik Ladkani 		ubi->beb_rsvd_level = 0;
12032608703STanya Brokhman 		ubi_warn(ubi, "number of bad PEBs (%d) is above the expected limit (%d), not reserving any PEBs for bad PEB handling, will use available PEBs (if any)",
12137f758a0SShmulik Ladkani 			 ubi->bad_peb_count, ubi->bad_peb_limit);
12237f758a0SShmulik Ladkani 	}
123801c135cSArtem B. Bityutskiy }
124bb00e180SArtem Bityutskiy 
125bb00e180SArtem Bityutskiy /**
126bb00e180SArtem Bityutskiy  * ubi_check_pattern - check if buffer contains only a certain byte pattern.
127bb00e180SArtem Bityutskiy  * @buf: buffer to check
128bb00e180SArtem Bityutskiy  * @patt: the pattern to check
129bb00e180SArtem Bityutskiy  * @size: buffer size in bytes
130bb00e180SArtem Bityutskiy  *
131bb00e180SArtem Bityutskiy  * This function returns %1 in there are only @patt bytes in @buf, and %0 if
132bb00e180SArtem Bityutskiy  * something else was also found.
133bb00e180SArtem Bityutskiy  */
ubi_check_pattern(const void * buf,uint8_t patt,int size)134bb00e180SArtem Bityutskiy int ubi_check_pattern(const void *buf, uint8_t patt, int size)
135bb00e180SArtem Bityutskiy {
136bb00e180SArtem Bityutskiy 	int i;
137bb00e180SArtem Bityutskiy 
138bb00e180SArtem Bityutskiy 	for (i = 0; i < size; i++)
139bb00e180SArtem Bityutskiy 		if (((const uint8_t *)buf)[i] != patt)
140bb00e180SArtem Bityutskiy 			return 0;
141bb00e180SArtem Bityutskiy 	return 1;
142bb00e180SArtem Bityutskiy }
14358d303deSJoe Perches 
14458d303deSJoe Perches /* Normal UBI messages */
ubi_msg(const struct ubi_device * ubi,const char * fmt,...)14558d303deSJoe Perches void ubi_msg(const struct ubi_device *ubi, const char *fmt, ...)
14658d303deSJoe Perches {
14758d303deSJoe Perches 	struct va_format vaf;
14858d303deSJoe Perches 	va_list args;
14958d303deSJoe Perches 
15058d303deSJoe Perches 	va_start(args, fmt);
15158d303deSJoe Perches 
15258d303deSJoe Perches 	vaf.fmt = fmt;
15358d303deSJoe Perches 	vaf.va = &args;
15458d303deSJoe Perches 
15558d303deSJoe Perches 	pr_notice(UBI_NAME_STR "%d: %pV\n", ubi->ubi_num, &vaf);
15658d303deSJoe Perches 
15758d303deSJoe Perches 	va_end(args);
15858d303deSJoe Perches }
15958d303deSJoe Perches 
16058d303deSJoe Perches /* UBI warning messages */
ubi_warn(const struct ubi_device * ubi,const char * fmt,...)16158d303deSJoe Perches void ubi_warn(const struct ubi_device *ubi, const char *fmt, ...)
16258d303deSJoe Perches {
16358d303deSJoe Perches 	struct va_format vaf;
16458d303deSJoe Perches 	va_list args;
16558d303deSJoe Perches 
16658d303deSJoe Perches 	va_start(args, fmt);
16758d303deSJoe Perches 
16858d303deSJoe Perches 	vaf.fmt = fmt;
16958d303deSJoe Perches 	vaf.va = &args;
17058d303deSJoe Perches 
17158d303deSJoe Perches 	pr_warn(UBI_NAME_STR "%d warning: %ps: %pV\n",
17258d303deSJoe Perches 		ubi->ubi_num, __builtin_return_address(0), &vaf);
17358d303deSJoe Perches 
17458d303deSJoe Perches 	va_end(args);
17558d303deSJoe Perches }
17658d303deSJoe Perches 
17758d303deSJoe Perches /* UBI error messages */
ubi_err(const struct ubi_device * ubi,const char * fmt,...)17858d303deSJoe Perches void ubi_err(const struct ubi_device *ubi, const char *fmt, ...)
17958d303deSJoe Perches {
18058d303deSJoe Perches 	struct va_format vaf;
18158d303deSJoe Perches 	va_list args;
18258d303deSJoe Perches 
18358d303deSJoe Perches 	va_start(args, fmt);
18458d303deSJoe Perches 
18558d303deSJoe Perches 	vaf.fmt = fmt;
18658d303deSJoe Perches 	vaf.va = &args;
18758d303deSJoe Perches 
18858d303deSJoe Perches 	pr_err(UBI_NAME_STR "%d error: %ps: %pV\n",
18958d303deSJoe Perches 	       ubi->ubi_num, __builtin_return_address(0), &vaf);
19058d303deSJoe Perches 	va_end(args);
19158d303deSJoe Perches }
192