diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-08-06 08:52:59 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-08-06 08:52:59 +0300 |
commit | 479058002c32b77acac43e883b92174e22c4be2d (patch) | |
tree | 9d1c295c0f185b8fc69f9450e8439b17d58a584f | |
parent | a530a36bb548bbd441402b736f17339183ff53fd (diff) | |
parent | 6cb43739b93c64c4a2148222bd606e6920257752 (diff) |
Merge tag 'ata-6.17-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux
Pull ata fixes from Damien Le Moal:
- Cleanup whitespace in messages in libata-core and the pata_pdc2027x,
pata_macio drivers (Colin)
- Fix ata_to_sense_error() to avoid seeing nonsensical sense data for
rare cases where we fail to get sense data from the drive. The
complementary fix to this is to ensure that we always return the
generic "ABORTED COMMAND" sense data for a failed command for which
we have no status or error fields
- The recent changes to link power management (LPM) which now prevent
the user from attempting to set an LPM policy through the
link_power_management_policy caused some regressions in test
environments because of the error that is now returned when writing
to that attribute when LPM is not supported. To allow users to not
trip on this, introduce the new link_power_management_supported
attribute to allow simple testing of a port/device LPM support (me)
* tag 'ata-6.17-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
ata: pata_pdc2027x: Remove space before newline and abbreviations
ata: pata_macio: Remove space before newline
ata: libata-core: Remove space before newline
ata: libata-sata: Add link_power_management_supported sysfs attribute
ata: libata-scsi: Return aborted command when missing sense and result TF
ata: libata-scsi: Fix ata_to_sense_error() status handling
-rw-r--r-- | drivers/ata/ata_piix.c | 1 | ||||
-rw-r--r-- | drivers/ata/libahci.c | 1 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-sata.c | 53 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 38 | ||||
-rw-r--r-- | drivers/ata/pata_macio.c | 2 | ||||
-rw-r--r-- | drivers/ata/pata_pdc2027x.c | 12 | ||||
-rw-r--r-- | include/linux/libata.h | 1 |
8 files changed, 71 insertions, 39 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 229429ba5027..495fa096dd65 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1089,6 +1089,7 @@ static struct ata_port_operations ich_pata_ops = { }; static struct attribute *piix_sidpr_shost_attrs[] = { + &dev_attr_link_power_management_supported.attr, &dev_attr_link_power_management_policy.attr, NULL }; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index b335fb7e5cb4..c79abdfcd7a9 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -111,6 +111,7 @@ static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO, static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL); static struct attribute *ahci_shost_attrs[] = { + &dev_attr_link_power_management_supported.attr, &dev_attr_link_power_management_policy.attr, &dev_attr_em_message_type.attr, &dev_attr_em_message.attr, diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 97d9f0488cc1..ff53f5f029b4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4602,7 +4602,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev, return AC_ERR_INVALID; /* set up init dev params taskfile */ - ata_dev_dbg(dev, "init dev params \n"); + ata_dev_dbg(dev, "init dev params\n"); ata_tf_init(dev, &tf); tf.command = ATA_CMD_INIT_DEV_PARAMS; diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 4734465d3b1e..b2817a2995d6 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -900,14 +900,52 @@ static const char *ata_lpm_policy_names[] = { [ATA_LPM_MIN_POWER] = "min_power", }; +/* + * Check if a port supports link power management. + * Must be called with the port locked. + */ +static bool ata_scsi_lpm_supported(struct ata_port *ap) +{ + struct ata_link *link; + struct ata_device *dev; + + if (ap->flags & ATA_FLAG_NO_LPM) + return false; + + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, &ap->link, ENABLED) { + if (dev->quirks & ATA_QUIRK_NOLPM) + return false; + } + } + + return true; +} + +static ssize_t ata_scsi_lpm_supported_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct ata_port *ap = ata_shost_to_port(shost); + unsigned long flags; + bool supported; + + spin_lock_irqsave(ap->lock, flags); + supported = ata_scsi_lpm_supported(ap); + spin_unlock_irqrestore(ap->lock, flags); + + return sysfs_emit(buf, "%d\n", supported); +} +DEVICE_ATTR(link_power_management_supported, S_IRUGO, + ata_scsi_lpm_supported_show, NULL); +EXPORT_SYMBOL_GPL(dev_attr_link_power_management_supported); + static ssize_t ata_scsi_lpm_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { struct Scsi_Host *shost = class_to_shost(device); struct ata_port *ap = ata_shost_to_port(shost); - struct ata_link *link; - struct ata_device *dev; enum ata_lpm_policy policy; unsigned long flags; @@ -924,20 +962,11 @@ static ssize_t ata_scsi_lpm_store(struct device *device, spin_lock_irqsave(ap->lock, flags); - if (ap->flags & ATA_FLAG_NO_LPM) { + if (!ata_scsi_lpm_supported(ap)) { count = -EOPNOTSUPP; goto out_unlock; } - ata_for_each_link(link, ap, EDGE) { - ata_for_each_dev(dev, &ap->link, ENABLED) { - if (dev->quirks & ATA_QUIRK_NOLPM) { - count = -EOPNOTSUPP; - goto out_unlock; - } - } - } - ap->target_lpm_policy = policy; ata_port_schedule_eh(ap); out_unlock: diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 27b15176db56..57f674f51b0c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -859,18 +859,14 @@ static void ata_to_sense_error(u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; static const unsigned char stat_table[][4] = { - /* Must be first because BUSY means no other bits valid */ - {0x80, ABORTED_COMMAND, 0x47, 0x00}, - // Busy, fake parity for now - {0x40, ILLEGAL_REQUEST, 0x21, 0x04}, - // Device ready, unaligned write command - {0x20, HARDWARE_ERROR, 0x44, 0x00}, - // Device fault, internal target failure - {0x08, ABORTED_COMMAND, 0x47, 0x00}, - // Timed out in xfer, fake parity for now - {0x04, RECOVERED_ERROR, 0x11, 0x00}, - // Recovered ECC error Medium error, recovered - {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + /* Busy: must be first because BUSY means no other bits valid */ + { ATA_BUSY, ABORTED_COMMAND, 0x00, 0x00 }, + /* Device fault: INTERNAL TARGET FAILURE */ + { ATA_DF, HARDWARE_ERROR, 0x44, 0x00 }, + /* Corrected data error */ + { ATA_CORR, RECOVERED_ERROR, 0x00, 0x00 }, + + { 0xFF, 0xFF, 0xFF, 0xFF }, /* END mark */ }; /* @@ -942,6 +938,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) { ata_dev_dbg(dev, "missing result TF: can't generate ATA PT sense data\n"); + if (qc->err_mask) + ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); return; } @@ -996,8 +994,8 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) { ata_dev_dbg(dev, - "missing result TF: can't generate sense data\n"); - return; + "Missing result TF: reporting aborted command\n"); + goto aborted; } /* Use ata_to_sense_error() to map status register bits @@ -1008,13 +1006,15 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) ata_to_sense_error(tf->status, tf->error, &sense_key, &asc, &ascq); ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq); - } else { - /* Could not decode error */ - ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", - tf->status, qc->err_mask); - ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); return; } + + /* Could not decode error */ + ata_dev_warn(dev, + "Could not decode error 0x%x, status 0x%x (err_mask=0x%x)\n", + tf->error, tf->status, qc->err_mask); +aborted: + ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); } void ata_scsi_sdev_config(struct scsi_device *sdev) diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index f7a933eefe05..9eefdc5df5df 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -758,7 +758,7 @@ static void pata_macio_irq_clear(struct ata_port *ap) static void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume) { - dev_dbg(priv->dev, "Enabling & resetting... \n"); + dev_dbg(priv->dev, "Enabling & resetting...\n"); if (priv->mediabay) return; diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index d792ce6d97bf..ae914dcb0c83 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -295,7 +295,7 @@ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) } /* Set the PIO timing registers using value table for 133MHz */ - ata_port_dbg(ap, "Set pio regs... \n"); + ata_port_dbg(ap, "Set PIO regs...\n"); ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0)); ctcr0 &= 0xffff0000; @@ -308,7 +308,7 @@ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24); iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); - ata_port_dbg(ap, "Set to pio mode[%u] \n", pio); + ata_port_dbg(ap, "Set to PIO mode[%u]\n", pio); } /** @@ -341,7 +341,7 @@ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) iowrite32(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1)); } - ata_port_dbg(ap, "Set udma regs... \n"); + ata_port_dbg(ap, "Set UDMA regs...\n"); ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1)); ctcr1 &= 0xff000000; @@ -350,14 +350,14 @@ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16); iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); - ata_port_dbg(ap, "Set to udma mode[%u] \n", udma_mode); + ata_port_dbg(ap, "Set to UDMA mode[%u]\n", udma_mode); } else if ((dma_mode >= XFER_MW_DMA_0) && (dma_mode <= XFER_MW_DMA_2)) { /* Set the MDMA timing registers with value table for 133MHz */ unsigned int mdma_mode = dma_mode & 0x07; - ata_port_dbg(ap, "Set mdma regs... \n"); + ata_port_dbg(ap, "Set MDMA regs...\n"); ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0)); ctcr0 &= 0x0000ffff; @@ -366,7 +366,7 @@ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); - ata_port_dbg(ap, "Set to mdma mode[%u] \n", mdma_mode); + ata_port_dbg(ap, "Set to MDMA mode[%u]\n", mdma_mode); } else { ata_port_err(ap, "Unknown dma mode [%u] ignored\n", dma_mode); } diff --git a/include/linux/libata.h b/include/linux/libata.h index 912ace523880..0620dd67369f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -545,6 +545,7 @@ typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes) extern struct device_attribute dev_attr_unload_heads; #ifdef CONFIG_SATA_HOST +extern struct device_attribute dev_attr_link_power_management_supported; extern struct device_attribute dev_attr_link_power_management_policy; extern struct device_attribute dev_attr_ncq_prio_supported; extern struct device_attribute dev_attr_ncq_prio_enable; |