Skip to content

Commit

Permalink
Merge tag 'ata-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/libata/linux

Pull ata updates from Niklas Cassel:

 - Add 'external' to the libata.force module parameter, in order to
   allow a user to workaround broken firmware (me)

 - Use the str_up_down() helper in the sata_via driver (Salah Triki)

 - Convert the Freescale PowerQUICC SATA device tree binding to YAML
   (J. Neuschäfer)

 - Do not use ATAPI DMA for a device that only supports PIO (me)

 - Add Marvell 88SE9215 PCI device ID to the ahci driver. Since the
   controller has quirks, it cannot rely on the generic AHCI PCI class
   code entry (Daniel Kral)

 - Improve the return value of atapi_check_dma() (Huacai Chen)

 - Fix the NCQ Non-Data log not supported print to actually reference
   the correct log (me)

 - Make Marvel 88SE9215 prefer DMA for ATAPI devices (Huacai Chen)

 - Simplify the AHCI IRQ vector allocations by performing the IRQ vector
   allocations in the same function, regardless of IRQ type (Tomas
   Henzl)

* tag 'ata-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: ahci: simplify init function
  ahci: Marvell 88SE9215 controllers prefer DMA for ATAPI
  ata: libata: Fix NCQ Non-Data log not supported print
  ata: libata: Improve return value of atapi_check_dma()
  ahci: add PCI ID for Marvell 88SE9215 SATA Controller
  ata: libata-eh: Do not use ATAPI DMA for a device limited to PIO mode
  dt-bindings: ata: Convert fsl,pq-sata to YAML
  ata: sata_via: Use str_up_down() helper in vt6420_prereset()
  ata: libata-core: Add 'external' to the libata.force kernel parameter
  • Loading branch information
Linus Torvalds committed Mar 27, 2025
2 parents 9b960d8 + 565d065 commit 2209399
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 44 deletions.
2 changes: 2 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3117,6 +3117,8 @@
* max_sec_lba48: Set or clear transfer size limit to
65535 sectors.

* external: Mark port as external (hotplug-capable).

* [no]lpm: Enable or disable link power management.

* [no]setxfer: Indicate if transfer speed mode setting
Expand Down
60 changes: 60 additions & 0 deletions Documentation/devicetree/bindings/ata/fsl,pq-sata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/ata/fsl,pq-sata.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Freescale 8xxx/3.0 Gb/s SATA nodes

maintainers:
- J. Neuschäfer <j.ne@posteo.net>

description:
SATA nodes are defined to describe on-chip Serial ATA controllers.
Each SATA controller should have its own node.

properties:
compatible:
oneOf:
- items:
- enum:
- fsl,mpc8377-sata
- fsl,mpc8536-sata
- fsl,mpc8315-sata
- fsl,mpc8379-sata
- const: fsl,pq-sata
- const: fsl,pq-sata-v2

reg:
maxItems: 1

interrupts:
maxItems: 1

cell-index:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2, 3, 4]
description: |
1 for controller @ 0x18000
2 for controller @ 0x19000
3 for controller @ 0x1a000
4 for controller @ 0x1b000
required:
- compatible
- interrupts
- cell-index

additionalProperties: false

examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
sata@18000 {
compatible = "fsl,mpc8379-sata", "fsl,pq-sata";
reg = <0x18000 0x1000>;
cell-index = <1>;
interrupts = <44 IRQ_TYPE_LEVEL_LOW>;
};
...
28 changes: 0 additions & 28 deletions Documentation/devicetree/bindings/ata/fsl-sata.txt

This file was deleted.

34 changes: 23 additions & 11 deletions drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -589,6 +598,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
.driver_data = board_ahci_yes_fbs },
{ 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_atapi_dma },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
.driver_data = board_ahci_yes_fbs },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235),
Expand Down Expand Up @@ -1665,13 +1676,15 @@ static int ahci_get_irq_vector(struct ata_host *host, int port)
return pci_irq_vector(to_pci_dev(host->dev), port);
}

static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
static void ahci_init_irq(struct pci_dev *pdev, unsigned int n_ports,
struct ahci_host_priv *hpriv)
{
int nvec;

if (hpriv->flags & AHCI_HFLAG_NO_MSI)
return -ENODEV;
if (hpriv->flags & AHCI_HFLAG_NO_MSI) {
pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX);
return;
}

/*
* If number of MSIs is less than number of ports then Sharing Last
Expand All @@ -1685,7 +1698,7 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
hpriv->get_irq_vector = ahci_get_irq_vector;
hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
return nvec;
return;
}

/*
Expand All @@ -1700,12 +1713,13 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,

/*
* If the host is not capable of supporting per-port vectors, fall
* back to single MSI before finally attempting single MSI-X.
* back to single MSI before finally attempting single MSI-X or
* a legacy INTx.
*/
nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
if (nvec == 1)
return nvec;
return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
return;
pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX | PCI_IRQ_INTX);
}

static void ahci_mark_external_port(struct ata_port *ap)
Expand Down Expand Up @@ -1985,10 +1999,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
host->private_data = hpriv;

if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
/* legacy intx interrupts */
pcim_intx(pdev, 1);
}
ahci_init_irq(pdev, n_ports, hpriv);

hpriv->irq = pci_irq_vector(pdev, 0);

if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
Expand Down
1 change: 1 addition & 0 deletions drivers/ata/ahci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
4 changes: 4 additions & 0 deletions drivers/ata/libahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,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,
Expand Down
42 changes: 40 additions & 2 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct ata_force_param {
unsigned int xfer_mask;
unsigned int quirk_on;
unsigned int quirk_off;
unsigned int pflags_on;
u16 lflags_on;
u16 lflags_off;
};
Expand Down Expand Up @@ -331,6 +332,35 @@ void ata_force_cbl(struct ata_port *ap)
}
}

/**
* ata_force_pflags - force port flags according to libata.force
* @ap: ATA port of interest
*
* Force port flags according to libata.force and whine about it.
*
* LOCKING:
* EH context.
*/
static void ata_force_pflags(struct ata_port *ap)
{
int i;

for (i = ata_force_tbl_size - 1; i >= 0; i--) {
const struct ata_force_ent *fe = &ata_force_tbl[i];

if (fe->port != -1 && fe->port != ap->print_id)
continue;

/* let pflags stack */
if (fe->param.pflags_on) {
ap->pflags |= fe->param.pflags_on;
ata_port_notice(ap,
"FORCE: port flag 0x%x forced -> 0x%x\n",
fe->param.pflags_on, ap->pflags);
}
}
}

/**
* ata_force_link_limits - force link limits according to libata.force
* @link: ATA link of interest
Expand Down Expand Up @@ -486,6 +516,7 @@ static void ata_force_quirks(struct ata_device *dev)
}
}
#else
static inline void ata_force_pflags(struct ata_port *ap) { }
static inline void ata_force_link_limits(struct ata_link *link) { }
static inline void ata_force_xfermask(struct ata_device *dev) { }
static inline void ata_force_quirks(struct ata_device *dev) { }
Expand Down Expand Up @@ -2243,7 +2274,7 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev)

if (!ata_log_supported(dev, ATA_LOG_NCQ_NON_DATA)) {
ata_dev_warn(dev,
"NCQ Send/Recv Log not supported\n");
"NCQ Non-Data Log not supported\n");
return;
}
err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_NON_DATA,
Expand Down Expand Up @@ -4552,7 +4583,7 @@ int atapi_check_dma(struct ata_queued_cmd *qc)
*/
if (!(qc->dev->quirks & ATA_QUIRK_ATAPI_MOD16_DMA) &&
unlikely(qc->nbytes & 15))
return 1;
return -EOPNOTSUPP;

if (ap->ops->check_atapi_dma)
return ap->ops->check_atapi_dma(qc);
Expand Down Expand Up @@ -5460,6 +5491,8 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
#endif
ata_sff_port_init(ap);

ata_force_pflags(ap);

return ap;
}
EXPORT_SYMBOL_GPL(ata_port_alloc);
Expand Down Expand Up @@ -6272,6 +6305,9 @@ EXPORT_SYMBOL_GPL(ata_platform_remove_one);
{ "no" #name, .lflags_on = (flags) }, \
{ #name, .lflags_off = (flags) }

#define force_pflag_on(name, flags) \
{ #name, .pflags_on = (flags) }

#define force_quirk_on(name, flag) \
{ #name, .quirk_on = (flag) }

Expand Down Expand Up @@ -6331,6 +6367,8 @@ static const struct ata_force_param force_tbl[] __initconst = {
force_lflag_on(rstonce, ATA_LFLAG_RST_ONCE),
force_lflag_onoff(dbdelay, ATA_LFLAG_NO_DEBOUNCE_DELAY),

force_pflag_on(external, ATA_PFLAG_EXTERNAL),

force_quirk_onoff(ncq, ATA_QUIRK_NONCQ),
force_quirk_onoff(ncqtrim, ATA_QUIRK_NO_NCQ_TRIM),
force_quirk_onoff(ncqati, ATA_QUIRK_NO_NCQ_ON_ATI),
Expand Down
11 changes: 9 additions & 2 deletions drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1542,8 +1542,15 @@ unsigned int atapi_eh_request_sense(struct ata_device *dev,
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.command = ATA_CMD_PACKET;

/* is it pointless to prefer PIO for "safety reasons"? */
if (ap->flags & ATA_FLAG_PIO_DMA) {
/*
* Do not use DMA if the connected device only supports PIO, even if the
* port prefers PIO commands via DMA.
*
* Ideally, we should call atapi_check_dma() to check if it is safe for
* the LLD to use DMA for REQUEST_SENSE, but we don't have a qc.
* Since we can't check the command, perhaps we should only use pio?
*/
if ((ap->flags & ATA_FLAG_PIO_DMA) && !(dev->flags & ATA_DFLAG_PIO)) {
tf.protocol = ATAPI_PROT_DMA;
tf.feature |= ATAPI_PKT_DMA;
} else {
Expand Down
3 changes: 2 additions & 1 deletion drivers/ata/sata_via.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#include <linux/string_choices.h>

#define DRV_NAME "sata_via"
#define DRV_VERSION "2.6"
Expand Down Expand Up @@ -359,7 +360,7 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)

ata_port_info(ap,
"SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
online ? "up" : "down", sstatus, scontrol);
str_up_down(online), sstatus, scontrol);

/* SStatus is read one more time */
svia_scr_read(link, SCR_STATUS, &sstatus);
Expand Down

0 comments on commit 2209399

Please sign in to comment.