/* This function returns zero in case of success and a negative error code in case of failure.  */
static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, unsigned char *buf)
/* This function returns zero in case of success and a negative error code in case of failure.  */
static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, unsigned char *buf)
{
	int err = 0, lnum, offs, total_read;
	struct gluebi_device *gluebi;
	if (len < 0 || from < 0 || from + len > mtd->size)
		return -EINVAL;
	gluebi = container_of(mtd, struct gluebi_device, mtd);
	lnum = div_u64_rem(from, mtd->erasesize, &offs);
	total_read = len;
	while (total_read) {
		size_t to_read = mtd->erasesize - offs;
		if (to_read > total_read)
			to_read = total_read;
		err = ubi_read(gluebi->desc, lnum, buf, offs, to_read);
		if (err)
			break;
		lnum += 1;
		offs = 0;
		total_read -= to_read;
		buf += to_read;
	}
	*retlen = len - total_read;
	return err;
}