* [PATCH] libata: fix ata_pio_sector for CONFIG_HIGHMEM
@ 2021-07-09 13:02 Christoph Hellwig
2021-07-09 14:28 ` Jens Axboe
2021-08-05 18:28 ` Sergei Shtylyov
0 siblings, 2 replies; 3+ messages in thread
From: Christoph Hellwig @ 2021-07-09 13:02 UTC (permalink / raw)
To: axboe; +Cc: torvalds, linux-ide, kernel test robot
Data transfers are not required to be block aligned in memory, so they
span two pages. Fix this by splitting the call to >sff_data_xfer into
two for that case.
This has been broken since the initial libata import before the damn
of git, but was uncovered by the legacy ide driver removal.
Reported-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/ata/libata-sff.c | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index ae7189d1a568..b71ea4a680b0 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -637,6 +637,20 @@ unsigned int ata_sff_data_xfer32(struct ata_queued_cmd *qc, unsigned char *buf,
}
EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
+static void ata_pio_xfer(struct ata_queued_cmd *qc, struct page *page,
+ unsigned int offset, size_t xfer_size)
+{
+ bool do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+ unsigned char *buf;
+
+ buf = kmap_atomic(page);
+ qc->ap->ops->sff_data_xfer(qc, buf + offset, xfer_size, do_write);
+ kunmap_atomic(buf);
+
+ if (!do_write && !PageSlab(page))
+ flush_dcache_page(page);
+}
+
/**
* ata_pio_sector - Transfer a sector of data.
* @qc: Command on going
@@ -648,11 +662,9 @@ EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
*/
static void ata_pio_sector(struct ata_queued_cmd *qc)
{
- int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
struct ata_port *ap = qc->ap;
struct page *page;
unsigned int offset;
- unsigned char *buf;
if (!qc->cursg) {
qc->curbytes = qc->nbytes;
@@ -670,13 +682,20 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
- /* do the actual data transfer */
- buf = kmap_atomic(page);
- ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size, do_write);
- kunmap_atomic(buf);
+ /*
+ * Split the transfer when it splits a page boundary. Note that the
+ * split still has to be dword aligned like all ATA data transfers.
+ */
+ WARN_ON_ONCE(offset % 4);
+ if (offset + qc->sect_size > PAGE_SIZE) {
+ unsigned int split_len = PAGE_SIZE - offset;
- if (!do_write && !PageSlab(page))
- flush_dcache_page(page);
+ ata_pio_xfer(qc, page, offset, split_len);
+ ata_pio_xfer(qc, nth_page(page, 1), 0,
+ qc->sect_size - split_len);
+ } else {
+ ata_pio_xfer(qc, page, offset, qc->sect_size);
+ }
qc->curbytes += qc->sect_size;
qc->cursg_ofs += qc->sect_size;
--
2.30.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] libata: fix ata_pio_sector for CONFIG_HIGHMEM
2021-07-09 13:02 [PATCH] libata: fix ata_pio_sector for CONFIG_HIGHMEM Christoph Hellwig
@ 2021-07-09 14:28 ` Jens Axboe
2021-08-05 18:28 ` Sergei Shtylyov
1 sibling, 0 replies; 3+ messages in thread
From: Jens Axboe @ 2021-07-09 14:28 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: torvalds, linux-ide, kernel test robot
On 7/9/21 7:02 AM, Christoph Hellwig wrote:
> Data transfers are not required to be block aligned in memory, so they
> span two pages. Fix this by splitting the call to >sff_data_xfer into
> two for that case.
>
> This has been broken since the initial libata import before the damn
> of git, but was uncovered by the legacy ide driver removal.
Applied, thanks.
--
Jens Axboe
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] libata: fix ata_pio_sector for CONFIG_HIGHMEM
2021-07-09 13:02 [PATCH] libata: fix ata_pio_sector for CONFIG_HIGHMEM Christoph Hellwig
2021-07-09 14:28 ` Jens Axboe
@ 2021-08-05 18:28 ` Sergei Shtylyov
1 sibling, 0 replies; 3+ messages in thread
From: Sergei Shtylyov @ 2021-08-05 18:28 UTC (permalink / raw)
To: Christoph Hellwig, axboe; +Cc: torvalds, linux-ide, kernel test robot
Hello!
On 7/9/21 4:02 PM, Christoph Hellwig wrote:
> Data transfers are not required to be block aligned in memory, so they
> span two pages. Fix this by splitting the call to >sff_data_xfer into
> two for that case.
>
> This has been broken since the initial libata import before the damn
> of git, but was uncovered by the legacy ide driver removal.
Damn of git, hehe... :-)
> Reported-by: kernel test robot <oliver.sang@intel.com>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
[...]
MBR, Sergei
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-08-05 18:28 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-09 13:02 [PATCH] libata: fix ata_pio_sector for CONFIG_HIGHMEM Christoph Hellwig
2021-07-09 14:28 ` Jens Axboe
2021-08-05 18:28 ` Sergei Shtylyov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.