]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ahci: Marvell 88SE9215 controllers prefer DMA for ATAPI
authorHuacai Chen <chenhuacai@loongson.cn>
Tue, 18 Mar 2025 10:43:14 +0000 (18:43 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 20 Apr 2025 08:15:21 +0000 (10:15 +0200)
[ Upstream commit 0507c777f5d8f9e34b137d28ee263599a7b81242 ]

We use CD/DVD drives under Marvell 88SE9215 SATA controller on many
Loongson-based machines. We found its PIO doesn't work well, and on the
opposite its DMA seems work very well.

We don't know the detail of the 88SE9215 SATA controller, but we have
tested different CD/DVD drives and they all have problems under 88SE9215
(but they all work well under an Intel SATA controller). So, we consider
this problem is bound to 88SE9215 SATA controller rather than bound to
CD/DVD drives.

As a solution, we define a new dedicated AHCI board id which is named
board_ahci_yes_fbs_atapi_dma for 88SE9215, and for this id we set the
AHCI_HFLAG_ATAPI_DMA_QUIRK and ATA_QUIRK_ATAPI_MOD16_DMA flags on the
SATA controller in order to prefer ATAPI DMA.

Reported-by: Yuli Wang <wangyuli@uniontech.com>
Tested-by: Jie Fan <fanjie@uniontech.com>
Tested-by: Erpeng Xu <xuerpeng@uniontech.com>
Tested-by: Yuli Wang <wangyuli@uniontech.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Link: https://lore.kernel.org/r/20250318104314.2160526-1-chenhuacai@loongson.cn
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/libahci.c

index 14dd1b432ac34af15d6e41b267bc7367c48554b7..650122deb480d09c809227adb7095795eb507cde 100644 (file)
@@ -63,6 +63,7 @@ enum board_ids {
        board_ahci_pcs_quirk_no_devslp,
        board_ahci_pcs_quirk_no_sntf,
        board_ahci_yes_fbs,
+       board_ahci_yes_fbs_atapi_dma,
 
        /* board IDs for specific chipsets in alphabetical order */
        board_ahci_al,
@@ -188,6 +189,14 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
+       [board_ahci_yes_fbs_atapi_dma] = {
+               AHCI_HFLAGS     (AHCI_HFLAG_YES_FBS |
+                                AHCI_HFLAG_ATAPI_DMA_QUIRK),
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_ops,
+       },
        /* by chipsets */
        [board_ahci_al] = {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI),
@@ -590,7 +599,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
          .driver_data = board_ahci_yes_fbs },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9215),
-         .driver_data = board_ahci_yes_fbs },
+         .driver_data = board_ahci_yes_fbs_atapi_dma },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
          .driver_data = board_ahci_yes_fbs },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235),
index 8f40f75ba08cff4deca261b1162ee9a0fb91fed6..10a5fe02f0a4535c36fc038b174872c853182c88 100644 (file)
@@ -246,6 +246,7 @@ enum {
        AHCI_HFLAG_NO_SXS               = BIT(26), /* SXS not supported */
        AHCI_HFLAG_43BIT_ONLY           = BIT(27), /* 43bit DMA addr limit */
        AHCI_HFLAG_INTEL_PCS_QUIRK      = BIT(28), /* apply Intel PCS quirk */
+       AHCI_HFLAG_ATAPI_DMA_QUIRK      = BIT(29), /* force ATAPI to use DMA */
 
        /* ap->flags bits */
 
index fdfa7b2662180b6593c7133f516edd0c5a8a048f..a28ffe1e5969182cf4b2025cb71325b26f6dedb1 100644 (file)
@@ -1321,6 +1321,10 @@ static void ahci_dev_config(struct ata_device *dev)
 {
        struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
 
+       if ((dev->class == ATA_DEV_ATAPI) &&
+           (hpriv->flags & AHCI_HFLAG_ATAPI_DMA_QUIRK))
+               dev->quirks |= ATA_QUIRK_ATAPI_MOD16_DMA;
+
        if (hpriv->flags & AHCI_HFLAG_SECT255) {
                dev->max_sectors = 255;
                ata_dev_info(dev,