ata changes for 6.14 part2

- Add ATA_QUIRK_NOLPM for Samsung SSD 870 QVO drives (Daniel)
 
  - Ensure that PIO transfers using libata-sff cannot write outside
    the allocated buffer (me)
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRN+ES/c4tHlMch3DzJZDGjmcZNcgUCZ5yslgAKCRDJZDGjmcZN
 ciwEAP4o64W9X+KBKOiZ+/BWoptT8rVKJR78ekjN9vwXwGRmtAEAqh+mY4CGnQEt
 LRmilEiSHbo+XwFrGh0PoPvprbS97Aw=
 =Gix2
 -----END PGP SIGNATURE-----

Merge tag 'ata-6.14-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

Pull more ata updates from Niklas Cassel:

 - Add ATA_QUIRK_NOLPM for Samsung SSD 870 QVO drives (Daniel)

 - Ensure that PIO transfers using libata-sff cannot write outside the
   allocated buffer (me)

* tag 'ata-6.14-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: libata-sff: Ensure that we cannot write outside the allocated buffer
  ata: libata-core: Add ATA_QUIRK_NOLPM for Samsung SSD 870 QVO drives
This commit is contained in:
Linus Torvalds 2025-01-31 11:07:56 -08:00
commit 95d7e82261
2 changed files with 14 additions and 8 deletions

View File

@ -4143,6 +4143,10 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
{ "Samsung SSD 860*", NULL, ATA_QUIRK_NO_NCQ_TRIM |
ATA_QUIRK_ZERO_AFTER_TRIM |
ATA_QUIRK_NO_NCQ_ON_ATI },
{ "Samsung SSD 870 QVO*", NULL, ATA_QUIRK_NO_NCQ_TRIM |
ATA_QUIRK_ZERO_AFTER_TRIM |
ATA_QUIRK_NO_NCQ_ON_ATI |
ATA_QUIRK_NOLPM },
{ "Samsung SSD 870*", NULL, ATA_QUIRK_NO_NCQ_TRIM |
ATA_QUIRK_ZERO_AFTER_TRIM |
ATA_QUIRK_NO_NCQ_ON_ATI },

View File

@ -601,7 +601,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct page *page;
unsigned int offset;
unsigned int offset, count;
if (!qc->cursg) {
qc->curbytes = qc->nbytes;
@ -617,25 +617,27 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
page = nth_page(page, (offset >> PAGE_SHIFT));
offset %= PAGE_SIZE;
trace_ata_sff_pio_transfer_data(qc, offset, qc->sect_size);
/* don't overrun current sg */
count = min(qc->cursg->length - qc->cursg_ofs, qc->sect_size);
trace_ata_sff_pio_transfer_data(qc, offset, count);
/*
* 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) {
if (offset + count > PAGE_SIZE) {
unsigned int split_len = PAGE_SIZE - offset;
ata_pio_xfer(qc, page, offset, split_len);
ata_pio_xfer(qc, nth_page(page, 1), 0,
qc->sect_size - split_len);
ata_pio_xfer(qc, nth_page(page, 1), 0, count - split_len);
} else {
ata_pio_xfer(qc, page, offset, qc->sect_size);
ata_pio_xfer(qc, page, offset, count);
}
qc->curbytes += qc->sect_size;
qc->cursg_ofs += qc->sect_size;
qc->curbytes += count;
qc->cursg_ofs += count;
if (qc->cursg_ofs == qc->cursg->length) {
qc->cursg = sg_next(qc->cursg);