|
@@ -375,56 +375,42 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
|
|
|
{
|
|
|
struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
|
|
|
struct onenand_chip *this = mtd->priv;
|
|
|
- dma_addr_t dma_src, dma_dst;
|
|
|
- int bram_offset;
|
|
|
+ struct device *dev = &c->pdev->dev;
|
|
|
void *buf = (void *)buffer;
|
|
|
+ dma_addr_t dma_src, dma_dst;
|
|
|
+ int bram_offset, err;
|
|
|
size_t xtra;
|
|
|
- int ret;
|
|
|
|
|
|
bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
|
|
|
- if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
|
|
|
- goto out_copy;
|
|
|
-
|
|
|
- /* panic_write() may be in an interrupt context */
|
|
|
- if (in_interrupt() || oops_in_progress)
|
|
|
+ /*
|
|
|
+ * If the buffer address is not DMA-able, len is not long enough to make
|
|
|
+ * DMA transfers profitable or panic_write() may be in an interrupt
|
|
|
+ * context fallback to PIO mode.
|
|
|
+ */
|
|
|
+ if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
|
|
|
+ count < 384 || in_interrupt() || oops_in_progress )
|
|
|
goto out_copy;
|
|
|
|
|
|
- if (buf >= high_memory) {
|
|
|
- struct page *p1;
|
|
|
-
|
|
|
- if (((size_t)buf & PAGE_MASK) !=
|
|
|
- ((size_t)(buf + count - 1) & PAGE_MASK))
|
|
|
- goto out_copy;
|
|
|
- p1 = vmalloc_to_page(buf);
|
|
|
- if (!p1)
|
|
|
- goto out_copy;
|
|
|
- buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
|
|
|
- }
|
|
|
-
|
|
|
xtra = count & 3;
|
|
|
if (xtra) {
|
|
|
count -= xtra;
|
|
|
memcpy(buf + count, this->base + bram_offset + count, xtra);
|
|
|
}
|
|
|
|
|
|
+ dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE);
|
|
|
dma_src = c->phys_base + bram_offset;
|
|
|
- dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
|
|
|
- if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
|
|
|
- dev_err(&c->pdev->dev,
|
|
|
- "Couldn't DMA map a %d byte buffer\n",
|
|
|
- count);
|
|
|
- goto out_copy;
|
|
|
- }
|
|
|
|
|
|
- ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
|
|
|
- dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
|
|
|
-
|
|
|
- if (ret) {
|
|
|
- dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
|
|
|
+ if (dma_mapping_error(dev, dma_dst)) {
|
|
|
+ dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count);
|
|
|
goto out_copy;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
|
|
|
+ dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE);
|
|
|
+ if (!err)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ dev_err(dev, "timeout waiting for DMA\n");
|
|
|
|
|
|
out_copy:
|
|
|
memcpy(buf, this->base + bram_offset, count);
|
|
@@ -437,49 +423,34 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
|
|
|
{
|
|
|
struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
|
|
|
struct onenand_chip *this = mtd->priv;
|
|
|
- dma_addr_t dma_src, dma_dst;
|
|
|
- int bram_offset;
|
|
|
+ struct device *dev = &c->pdev->dev;
|
|
|
void *buf = (void *)buffer;
|
|
|
- int ret;
|
|
|
+ dma_addr_t dma_src, dma_dst;
|
|
|
+ int bram_offset, err;
|
|
|
|
|
|
bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
|
|
|
- if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
|
|
|
- goto out_copy;
|
|
|
-
|
|
|
- /* panic_write() may be in an interrupt context */
|
|
|
- if (in_interrupt() || oops_in_progress)
|
|
|
+ /*
|
|
|
+ * If the buffer address is not DMA-able, len is not long enough to make
|
|
|
+ * DMA transfers profitable or panic_write() may be in an interrupt
|
|
|
+ * context fallback to PIO mode.
|
|
|
+ */
|
|
|
+ if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
|
|
|
+ count < 384 || in_interrupt() || oops_in_progress )
|
|
|
goto out_copy;
|
|
|
|
|
|
- if (buf >= high_memory) {
|
|
|
- struct page *p1;
|
|
|
-
|
|
|
- if (((size_t)buf & PAGE_MASK) !=
|
|
|
- ((size_t)(buf + count - 1) & PAGE_MASK))
|
|
|
- goto out_copy;
|
|
|
- p1 = vmalloc_to_page(buf);
|
|
|
- if (!p1)
|
|
|
- goto out_copy;
|
|
|
- buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
|
|
|
- }
|
|
|
-
|
|
|
- dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
|
|
|
+ dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
|
|
|
dma_dst = c->phys_base + bram_offset;
|
|
|
- if (dma_mapping_error(&c->pdev->dev, dma_src)) {
|
|
|
- dev_err(&c->pdev->dev,
|
|
|
- "Couldn't DMA map a %d byte buffer\n",
|
|
|
- count);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
|
|
|
- dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE);
|
|
|
-
|
|
|
- if (ret) {
|
|
|
- dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
|
|
|
+ if (dma_mapping_error(dev, dma_src)) {
|
|
|
+ dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count);
|
|
|
goto out_copy;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
|
|
|
+ dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE);
|
|
|
+ if (!err)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ dev_err(dev, "timeout waiting for DMA\n");
|
|
|
|
|
|
out_copy:
|
|
|
memcpy(this->base + bram_offset, buf, count);
|