mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
ata fixes for 6.17-rc1
- 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). -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQSRPv8tYSvhwAzJdzjdoc3SxdoYdgUCaJLfKAAKCRDdoc3SxdoY djDMAQDiz6WkgTKrJpRLkYYjsePRBRq4xFFJkD0U/82+UW653wEA3JLO3eoy6u8O 2/0DEisPnzfMj42NIMlNFbDRd3FHwg8= =h28h -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
479058002c
8 changed files with 71 additions and 39 deletions
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue