diff options
-rw-r--r-- | Documentation/admin-guide/kernel-parameters.txt | 2 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/ata/fsl,pq-sata.yaml | 60 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/ata/fsl-sata.txt | 28 | ||||
-rw-r--r-- | drivers/ata/ahci.c | 34 | ||||
-rw-r--r-- | drivers/ata/ahci.h | 1 | ||||
-rw-r--r-- | drivers/ata/libahci.c | 4 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 42 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 11 | ||||
-rw-r--r-- | drivers/ata/sata_via.c | 3 |
9 files changed, 141 insertions, 44 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index f0f1b9e0ebcb..637c933c5478 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -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 diff --git a/Documentation/devicetree/bindings/ata/fsl,pq-sata.yaml b/Documentation/devicetree/bindings/ata/fsl,pq-sata.yaml new file mode 100644 index 000000000000..1d19ee832f0c --- /dev/null +++ b/Documentation/devicetree/bindings/ata/fsl,pq-sata.yaml @@ -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>; + }; + +... diff --git a/Documentation/devicetree/bindings/ata/fsl-sata.txt b/Documentation/devicetree/bindings/ata/fsl-sata.txt deleted file mode 100644 index fd63bb3becc9..000000000000 --- a/Documentation/devicetree/bindings/ata/fsl-sata.txt +++ /dev/null @@ -1,28 +0,0 @@ -* Freescale 8xxx/3.0 Gb/s SATA nodes - -SATA nodes are defined to describe on-chip Serial ATA controllers. -Each SATA port should have its own node. - -Required properties: -- compatible : compatible list, contains 2 entries, first is - "fsl,CHIP-sata", where CHIP is the processor - (mpc8315, mpc8379, etc.) and the second is - "fsl,pq-sata" -- interrupts : <interrupt mapping for SATA IRQ> -- cell-index : controller index. - 1 for controller @ 0x18000 - 2 for controller @ 0x19000 - 3 for controller @ 0x1a000 - 4 for controller @ 0x1b000 - -Optional properties: -- reg : <registers mapping> - -Example: - sata@18000 { - compatible = "fsl,mpc8379-sata", "fsl,pq-sata"; - reg = <0x18000 0x1000>; - cell-index = <1>; - interrupts = <2c 8>; - interrupt-parent = < &ipic >; - }; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f813dbdc2346..163ac909bd06 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -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), @@ -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), @@ -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 @@ -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; } /* @@ -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) @@ -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) diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index c842e2de6ef9..2c10c8f440d1 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -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 */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index e7ace4b10f15..22afa4ff860d 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -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, diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d956735e2a76..773799cfd443 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -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; }; @@ -332,6 +333,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 * @@ -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) { } @@ -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, @@ -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); @@ -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); @@ -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) } @@ -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), diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 3b303d4ae37a..16cd676eae1f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -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 { diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 57cbf2cef618..4ecd8f33b082 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -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" @@ -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); |