aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLadislav Michl <ladis@linux-mips.org>2018-05-02 06:41:32 -0400
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-05-02 09:17:18 -0400
commit6732cfd4cac514b556f36b518670af91c8bdf19a (patch)
tree628fd72e2b4ea3398cb71ef87e9bdd1a4c8da4e1
parent6da6c0db5316275015e8cc2959f12a17584aeb64 (diff)
mtd: onenand: omap2: Disable DMA for HIGHMEM buffers
dma_map_single does not work for vmalloc-ed buffers, so disable DMA in this case. Signed-off-by: Ladislav Michl <ladis@linux-mips.org> Reported-by: "H. Nikolaus Schaller" <hns@goldelico.com> Tested-by: "H. Nikolaus Schaller" <hns@goldelico.com> Reviewed-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-rw-r--r--drivers/mtd/nand/onenand/omap2.c105
1 files changed, 38 insertions, 67 deletions
diff --git a/drivers/mtd/nand/onenand/omap2.c b/drivers/mtd/nand/onenand/omap2.c
index 9c159f0dd9a6..321137158ff3 100644
--- a/drivers/mtd/nand/onenand/omap2.c
+++ b/drivers/mtd/nand/onenand/omap2.c
@@ -375,56 +375,42 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
375{ 375{
376 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); 376 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
377 struct onenand_chip *this = mtd->priv; 377 struct onenand_chip *this = mtd->priv;
378 dma_addr_t dma_src, dma_dst; 378 struct device *dev = &c->pdev->dev;
379 int bram_offset;
380 void *buf = (void *)buffer; 379 void *buf = (void *)buffer;
380 dma_addr_t dma_src, dma_dst;
381 int bram_offset, err;
381 size_t xtra; 382 size_t xtra;
382 int ret;
383 383
384 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset; 384 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
385 if (bram_offset & 3 || (size_t)buf & 3 || count < 384) 385 /*
386 goto out_copy; 386 * If the buffer address is not DMA-able, len is not long enough to make
387 387 * DMA transfers profitable or panic_write() may be in an interrupt
388 /* panic_write() may be in an interrupt context */ 388 * context fallback to PIO mode.
389 if (in_interrupt() || oops_in_progress) 389 */
390 if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
391 count < 384 || in_interrupt() || oops_in_progress )
390 goto out_copy; 392 goto out_copy;
391 393
392 if (buf >= high_memory) {
393 struct page *p1;
394
395 if (((size_t)buf & PAGE_MASK) !=
396 ((size_t)(buf + count - 1) & PAGE_MASK))
397 goto out_copy;
398 p1 = vmalloc_to_page(buf);
399 if (!p1)
400 goto out_copy;
401 buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
402 }
403
404 xtra = count & 3; 394 xtra = count & 3;
405 if (xtra) { 395 if (xtra) {
406 count -= xtra; 396 count -= xtra;
407 memcpy(buf + count, this->base + bram_offset + count, xtra); 397 memcpy(buf + count, this->base + bram_offset + count, xtra);
408 } 398 }
409 399
400 dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE);
410 dma_src = c->phys_base + bram_offset; 401 dma_src = c->phys_base + bram_offset;
411 dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
412 if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
413 dev_err(&c->pdev->dev,
414 "Couldn't DMA map a %d byte buffer\n",
415 count);
416 goto out_copy;
417 }
418 402
419 ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count); 403 if (dma_mapping_error(dev, dma_dst)) {
420 dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE); 404 dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count);
421
422 if (ret) {
423 dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
424 goto out_copy; 405 goto out_copy;
425 } 406 }
426 407
427 return 0; 408 err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
409 dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE);
410 if (!err)
411 return 0;
412
413 dev_err(dev, "timeout waiting for DMA\n");
428 414
429out_copy: 415out_copy:
430 memcpy(buf, this->base + bram_offset, count); 416 memcpy(buf, this->base + bram_offset, count);
@@ -437,49 +423,34 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
437{ 423{
438 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); 424 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
439 struct onenand_chip *this = mtd->priv; 425 struct onenand_chip *this = mtd->priv;
440 dma_addr_t dma_src, dma_dst; 426 struct device *dev = &c->pdev->dev;
441 int bram_offset;
442 void *buf = (void *)buffer; 427 void *buf = (void *)buffer;
443 int ret; 428 dma_addr_t dma_src, dma_dst;
429 int bram_offset, err;
444 430
445 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset; 431 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
446 if (bram_offset & 3 || (size_t)buf & 3 || count < 384) 432 /*
447 goto out_copy; 433 * If the buffer address is not DMA-able, len is not long enough to make
448 434 * DMA transfers profitable or panic_write() may be in an interrupt
449 /* panic_write() may be in an interrupt context */ 435 * context fallback to PIO mode.
450 if (in_interrupt() || oops_in_progress) 436 */
437 if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
438 count < 384 || in_interrupt() || oops_in_progress )
451 goto out_copy; 439 goto out_copy;
452 440
453 if (buf >= high_memory) { 441 dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
454 struct page *p1;
455
456 if (((size_t)buf & PAGE_MASK) !=
457 ((size_t)(buf + count - 1) & PAGE_MASK))
458 goto out_copy;
459 p1 = vmalloc_to_page(buf);
460 if (!p1)
461 goto out_copy;
462 buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
463 }
464
465 dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
466 dma_dst = c->phys_base + bram_offset; 442 dma_dst = c->phys_base + bram_offset;
467 if (dma_mapping_error(&c->pdev->dev, dma_src)) { 443 if (dma_mapping_error(dev, dma_src)) {
468 dev_err(&c->pdev->dev, 444 dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count);
469 "Couldn't DMA map a %d byte buffer\n",
470 count);
471 return -1;
472 }
473
474 ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
475 dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE);
476
477 if (ret) {
478 dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
479 goto out_copy; 445 goto out_copy;
480 } 446 }
481 447
482 return 0; 448 err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
449 dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE);
450 if (!err)
451 return 0;
452
453 dev_err(dev, "timeout waiting for DMA\n");
483 454
484out_copy: 455out_copy:
485 memcpy(this->base + bram_offset, buf, count); 456 memcpy(this->base + bram_offset, buf, count);