[PATCH 09/10] mtd: nand: gpmi: rework gpmi_ecc_write_page

Sascha Hauer s.hauer at pengutronix.de
Wed Dec 6 01:19:24 PST 2017


gpmi_ecc_write_page() used to call several functions with 8 arguments
each. refactor this to make it easier to follow.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 140 ++++++++++-----------------------
 1 file changed, 42 insertions(+), 98 deletions(-)

diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 8dc40b672ab9..d8038b62246c 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -695,51 +695,6 @@ static int init_hardware(struct gpmi_nand_data *this)
 	return 0;
 }
 
-static int send_page_prepare(struct gpmi_nand_data *this,
-			const void *source, unsigned length,
-			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
-			const void **use_virt, dma_addr_t *use_phys)
-{
-	struct device *dev = this->dev;
-
-	if (virt_addr_valid(source)) {
-		dma_addr_t source_phys;
-
-		source_phys = dma_map_single(dev, (void *)source, length,
-						DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, source_phys)) {
-			if (alt_size < length) {
-				dev_err(dev, "Alternate buffer is too small\n");
-				return -ENOMEM;
-			}
-			goto map_failed;
-		}
-		*use_virt = source;
-		*use_phys = source_phys;
-		return 0;
-	}
-map_failed:
-	/*
-	 * Copy the content of the source buffer into the alternate
-	 * buffer and set up the return values accordingly.
-	 */
-	memcpy(alt_virt, source, length);
-
-	*use_virt = alt_virt;
-	*use_phys = alt_phys;
-	return 0;
-}
-
-static void send_page_end(struct gpmi_nand_data *this,
-			const void *source, unsigned length,
-			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
-			const void *used_virt, dma_addr_t used_phys)
-{
-	struct device *dev = this->dev;
-	if (used_virt == source)
-		dma_unmap_single(dev, used_phys, length, DMA_TO_DEVICE);
-}
-
 static void gpmi_free_dma_buffer(struct gpmi_nand_data *this)
 {
 	struct device *dev = this->dev;
@@ -1126,60 +1081,53 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 	return max_bitflips;
 }
 
+
+static bool map_write_direct(struct gpmi_nand_data *this, const void *source,
+		       unsigned length, dma_addr_t *phys)
+{
+	struct device *dev = this->dev;
+	dma_addr_t source_phys;
+
+	/*
+	 * input data is const, we cannot map directly when doing bad block
+	 * marker swapping.
+	 */
+	if (this->swap_block_mark)
+		return false;
+
+	if (!virt_addr_valid(source))
+		return false;
+
+	source_phys = dma_map_single(dev, (void *)source, length,
+					DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, source_phys))
+		return false;
+
+	return true;
+}
+
 static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 				const uint8_t *buf, int oob_required, int page)
 {
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
-	struct bch_geometry *nfc_geo = &this->bch_geometry;
-	const void *payload_virt;
 	dma_addr_t payload_phys;
-	const void *auxiliary_virt;
 	dma_addr_t auxiliary_phys;
-	int        ret;
+	int ret;
+	bool user_mapped, oob_mapped;
 
 	dev_dbg(this->dev, "ecc write page.\n");
-	if (this->swap_block_mark) {
-		/*
-		 * If control arrives here, we're doing block mark swapping.
-		 * Since we can't modify the caller's buffers, we must copy them
-		 * into our own.
-		 */
+
+	user_mapped = map_write_direct(this, buf, mtd->writesize, &payload_phys);
+	if (!user_mapped) {
 		memcpy(this->payload_virt, buf, mtd->writesize);
-		payload_virt = this->payload_virt;
 		payload_phys = this->payload_phys;
+	}
 
-		memcpy(this->auxiliary_virt, chip->oob_poi,
-				nfc_geo->auxiliary_size);
-		auxiliary_virt = this->auxiliary_virt;
+	oob_mapped = map_write_direct(this, chip->oob_poi, mtd->oobsize,
+				&auxiliary_phys);
+	if (!oob_mapped) {
+		memcpy(this->auxiliary_virt, buf, mtd->oobsize);
 		auxiliary_phys = this->auxiliary_phys;
-
-		/* Handle block mark swapping. */
-		block_mark_swapping(this,
-				(void *)payload_virt, (void *)auxiliary_virt);
-	} else {
-		/*
-		 * If control arrives here, we're not doing block mark swapping,
-		 * so we can to try and use the caller's buffers.
-		 */
-		ret = send_page_prepare(this,
-				buf, mtd->writesize,
-				this->payload_virt, this->payload_phys,
-				nfc_geo->payload_size,
-				&payload_virt, &payload_phys);
-		if (ret) {
-			dev_err(this->dev, "Inadequate payload DMA buffer\n");
-			return 0;
-		}
-
-		ret = send_page_prepare(this,
-				chip->oob_poi, mtd->oobsize,
-				this->auxiliary_virt, this->auxiliary_phys,
-				nfc_geo->auxiliary_size,
-				&auxiliary_virt, &auxiliary_phys);
-		if (ret) {
-			dev_err(this->dev, "Inadequate auxiliary DMA buffer\n");
-			goto exit_auxiliary;
-		}
 	}
 
 	/* Ask the NFC. */
@@ -1187,17 +1135,13 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	if (ret)
 		dev_err(this->dev, "Error in ECC-based write: %d\n", ret);
 
-	if (!this->swap_block_mark) {
-		send_page_end(this, chip->oob_poi, mtd->oobsize,
-				this->auxiliary_virt, this->auxiliary_phys,
-				nfc_geo->auxiliary_size,
-				auxiliary_virt, auxiliary_phys);
-exit_auxiliary:
-		send_page_end(this, buf, mtd->writesize,
-				this->payload_virt, this->payload_phys,
-				nfc_geo->payload_size,
-				payload_virt, payload_phys);
-	}
+	if (oob_mapped)
+		dma_unmap_single(this->dev, auxiliary_phys, mtd->oobsize,
+				 DMA_TO_DEVICE);
+
+	if (user_mapped)
+		dma_unmap_single(this->dev, payload_phys, mtd->writesize,
+				 DMA_TO_DEVICE);
 
 	return 0;
 }
-- 
2.11.0




More information about the linux-mtd mailing list