drivers/mtd/nand/ecc-sw-hamming.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/ecc-sw-hamming.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/ecc-sw-hamming.c
Extension
.c
Size
19758 bytes
Lines
661
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (mtd->oobsize) {
		case 8:
		case 16:
			mtd_set_ooblayout(mtd, nand_get_small_page_ooblayout());
			break;
		case 64:
		case 128:
			mtd_set_ooblayout(mtd,
					  nand_get_large_page_hamming_ooblayout());
			break;
		default:
			return -ENOTSUPP;
		}
	}

	conf->engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
	conf->algo = NAND_ECC_ALGO_HAMMING;
	conf->step_size = nand->ecc.user_conf.step_size;
	conf->strength = 1;

	/* Use the strongest configuration by default */
	if (conf->step_size != 256 && conf->step_size != 512)
		conf->step_size = 256;

	engine_conf = kzalloc_obj(*engine_conf);
	if (!engine_conf)
		return -ENOMEM;

	ret = nand_ecc_init_req_tweaking(&engine_conf->req_ctx, nand);
	if (ret)
		goto free_engine_conf;

	engine_conf->code_size = 3;
	engine_conf->calc_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
	engine_conf->code_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
	if (!engine_conf->calc_buf || !engine_conf->code_buf) {
		ret = -ENOMEM;
		goto free_bufs;
	}

	nand->ecc.ctx.priv = engine_conf;
	nand->ecc.ctx.nsteps = mtd->writesize / conf->step_size;
	nand->ecc.ctx.total = nand->ecc.ctx.nsteps * engine_conf->code_size;

	return 0;

free_bufs:
	nand_ecc_cleanup_req_tweaking(&engine_conf->req_ctx);
	kfree(engine_conf->calc_buf);
	kfree(engine_conf->code_buf);
free_engine_conf:
	kfree(engine_conf);

	return ret;
}
EXPORT_SYMBOL(nand_ecc_sw_hamming_init_ctx);

void nand_ecc_sw_hamming_cleanup_ctx(struct nand_device *nand)
{
	struct nand_ecc_sw_hamming_conf *engine_conf = nand->ecc.ctx.priv;

	if (engine_conf) {
		nand_ecc_cleanup_req_tweaking(&engine_conf->req_ctx);
		kfree(engine_conf->calc_buf);
		kfree(engine_conf->code_buf);
		kfree(engine_conf);
	}
}
EXPORT_SYMBOL(nand_ecc_sw_hamming_cleanup_ctx);

static int nand_ecc_sw_hamming_prepare_io_req(struct nand_device *nand,
					      struct nand_page_io_req *req)
{
	struct nand_ecc_sw_hamming_conf *engine_conf = nand->ecc.ctx.priv;
	struct mtd_info *mtd = nanddev_to_mtd(nand);
	int eccsize = nand->ecc.ctx.conf.step_size;
	int eccbytes = engine_conf->code_size;
	int eccsteps = nand->ecc.ctx.nsteps;
	int total = nand->ecc.ctx.total;
	u8 *ecccalc = engine_conf->calc_buf;
	const u8 *data;
	int i;

	/* Nothing to do for a raw operation */
	if (req->mode == MTD_OPS_RAW)
		return 0;

	/* This engine does not provide BBM/free OOB bytes protection */
	if (!req->datalen)
		return 0;

Annotation

Implementation Notes