static int msb_write_block()

in core/ms_block.c [1000:1077]


static int msb_write_block(struct msb_data *msb,
			u16 pba, u32 lba, struct scatterlist *sg, int offset)
{
	int error, current_try = 1;

	BUG_ON(sg->length < msb->page_size);

	if (msb->read_only)
		return -EROFS;

	if (pba == MS_BLOCK_INVALID) {
		pr_err(
			"BUG: write: attempt to write MS_BLOCK_INVALID block");
		return -EINVAL;
	}

	if (pba >= msb->block_count || lba >= msb->logical_block_count) {
		pr_err(
		"BUG: write: attempt to write beyond the end of device");
		return -EINVAL;
	}

	if (msb_get_zone_from_lba(lba) != msb_get_zone_from_pba(pba)) {
		pr_err("BUG: write: lba zone mismatch");
		return -EINVAL;
	}

	if (pba == msb->boot_block_locations[0] ||
		pba == msb->boot_block_locations[1]) {
		pr_err("BUG: write: attempt to write to boot blocks!");
		return -EINVAL;
	}

	while (1) {

		if (msb->read_only)
			return -EROFS;

		msb->regs.param.cp = MEMSTICK_CP_BLOCK;
		msb->regs.param.page_address = 0;
		msb->regs.param.block_address = cpu_to_be16(pba);

		msb->regs.extra_data.management_flag = 0xFF;
		msb->regs.extra_data.overwrite_flag = 0xF8;
		msb->regs.extra_data.logical_address = cpu_to_be16(lba);

		msb->current_sg = sg;
		msb->current_sg_offset = offset;
		msb->current_page = 0;

		error = msb_run_state_machine(msb, h_msb_write_block);

		/* Sector we just wrote to is assumed erased since its pba
		 * was erased. If it wasn't erased, write will succeed
		 * and will just clear the bits that were set in the block
		 * thus test that what we have written,
		 * matches what we expect.
		 * We do trust the blocks that we erased
		 */
		if (!error && (verify_writes ||
				!test_bit(pba, msb->erased_blocks_bitmap)))
			error = msb_verify_block(msb, pba, sg, offset);

		if (!error)
			break;

		if (current_try > 1 || msb_reset(msb, true))
			break;

		pr_err("write failed, trying to erase the pba %d", pba);
		error = msb_erase_block(msb, pba);
		if (error)
			break;

		current_try++;
	}
	return error;
}