Commit cc3e5afc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ata fixes from Damien Le Moal:

 - Fix link power management transitions to disallow unsupported states
   (Niklas)

 - A small string handling fix for the sata_mv driver (Christophe)

 - Clear port pending interrupts before reset, as per AHCI
   specifications (Szuying).

   Followup fixes for this one are to not clear ATA_PFLAG_EH_PENDING in
   ata_eh_reset() to allow EH to continue on with other actions recorded
   with error interrupts triggered before EH completes. And an
   additional fix to avoid thawing a port twice in EH (Niklas)

 - Small code style fixes in the pata_parport driver to silence the
   build bot as it keeps complaining about bad indentation (me)

 - A fix for the recent CDL code to avoid fetching sense data for
   successful commands when not necessary for correct operation (Niklas)

* tag 'ata-6.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata:
  ata: libata-core: fetch sense data for successful commands iff CDL enabled
  ata: libata-eh: do not thaw the port twice in ata_eh_reset()
  ata: libata-eh: do not clear ATA_PFLAG_EH_PENDING in ata_eh_reset()
  ata: pata_parport: Fix code style issues
  ata: libahci: clear pending interrupt status
  ata: sata_mv: Fix incorrect string length computation in mv_dump_mem()
  ata: libata: disallow dev-initiated LPM transitions to unsupported states
parents cce67b6b 5e35a9ac
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1883,6 +1883,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	else
		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");

	if (!(hpriv->cap & HOST_CAP_PART))
		host->flags |= ATA_HOST_NO_PART;

	if (!(hpriv->cap & HOST_CAP_SSC))
		host->flags |= ATA_HOST_NO_SSC;

	if (!(hpriv->cap2 & HOST_CAP2_SDS))
		host->flags |= ATA_HOST_NO_DEVSLP;

	if (pi.flags & ATA_FLAG_EM)
		ahci_reset_em(host);

+23 −12
Original line number Diff line number Diff line
@@ -1256,6 +1256,26 @@ static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
	return sprintf(buf, "%d\n", emp->blink_policy);
}

static void ahci_port_clear_pending_irq(struct ata_port *ap)
{
	struct ahci_host_priv *hpriv = ap->host->private_data;
	void __iomem *port_mmio = ahci_port_base(ap);
	u32 tmp;

	/* clear SError */
	tmp = readl(port_mmio + PORT_SCR_ERR);
	dev_dbg(ap->host->dev, "PORT_SCR_ERR 0x%x\n", tmp);
	writel(tmp, port_mmio + PORT_SCR_ERR);

	/* clear port IRQ */
	tmp = readl(port_mmio + PORT_IRQ_STAT);
	dev_dbg(ap->host->dev, "PORT_IRQ_STAT 0x%x\n", tmp);
	if (tmp)
		writel(tmp, port_mmio + PORT_IRQ_STAT);

	writel(1 << ap->port_no, hpriv->mmio + HOST_IRQ_STAT);
}

static void ahci_port_init(struct device *dev, struct ata_port *ap,
			   int port_no, void __iomem *mmio,
			   void __iomem *port_mmio)
@@ -1270,18 +1290,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
	if (rc)
		dev_warn(dev, "%s (%d)\n", emsg, rc);

	/* clear SError */
	tmp = readl(port_mmio + PORT_SCR_ERR);
	dev_dbg(dev, "PORT_SCR_ERR 0x%x\n", tmp);
	writel(tmp, port_mmio + PORT_SCR_ERR);

	/* clear port IRQ */
	tmp = readl(port_mmio + PORT_IRQ_STAT);
	dev_dbg(dev, "PORT_IRQ_STAT 0x%x\n", tmp);
	if (tmp)
		writel(tmp, port_mmio + PORT_IRQ_STAT);

	writel(1 << port_no, mmio + HOST_IRQ_STAT);
	ahci_port_clear_pending_irq(ap);

	/* mark esata ports */
	tmp = readl(port_mmio + PORT_CMD);
@@ -1603,6 +1612,8 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
	tf.status = ATA_BUSY;
	ata_tf_to_fis(&tf, 0, 0, d2h_fis);

	ahci_port_clear_pending_irq(ap);

	rc = sata_link_hardreset(link, timing, deadline, online,
				 ahci_check_ready);

+2 −5
Original line number Diff line number Diff line
@@ -4783,11 +4783,8 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
	 * been aborted by the device due to a limit timeout using the policy
	 * 0xD. For these commands, invoke EH to get the command sense data.
	 */
	if (qc->result_tf.status & ATA_SENSE &&
	    ((ata_is_ncq(qc->tf.protocol) &&
	      dev->flags & ATA_DFLAG_CDL_ENABLED) ||
	     (!ata_is_ncq(qc->tf.protocol) &&
	      ata_id_sense_reporting_enabled(dev->id)))) {
	if (qc->flags & ATA_QCFLAG_HAS_CDL &&
	    qc->result_tf.status & ATA_SENSE) {
		/*
		 * Tell SCSI EH to not overwrite scmd->result even if this
		 * command is finished with result SAM_STAT_GOOD.
+3 −13
Original line number Diff line number Diff line
@@ -2796,23 +2796,13 @@ int ata_eh_reset(struct ata_link *link, int classify,
		}
	}

	/*
	 * Some controllers can't be frozen very well and may set spurious
	 * error conditions during reset.  Clear accumulated error
	 * information and re-thaw the port if frozen.  As reset is the
	 * final recovery action and we cross check link onlineness against
	 * device classification later, no hotplug event is lost by this.
	 */
	/* clear cached SError */
	spin_lock_irqsave(link->ap->lock, flags);
	memset(&link->eh_info, 0, sizeof(link->eh_info));
	link->eh_info.serror = 0;
	if (slave)
		memset(&slave->eh_info, 0, sizeof(link->eh_info));
	ap->pflags &= ~ATA_PFLAG_EH_PENDING;
		slave->eh_info.serror = 0;
	spin_unlock_irqrestore(link->ap->lock, flags);

	if (ata_port_is_frozen(ap))
		ata_eh_thaw_port(ap);

	/*
	 * Make sure onlineness and classification result correspond.
	 * Hotplug could have happened during reset and some
+16 −3
Original line number Diff line number Diff line
@@ -396,10 +396,23 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
	case ATA_LPM_MED_POWER_WITH_DIPM:
	case ATA_LPM_MIN_POWER_WITH_PARTIAL:
	case ATA_LPM_MIN_POWER:
		if (ata_link_nr_enabled(link) > 0)
			/* no restrictions on LPM transitions */
		if (ata_link_nr_enabled(link) > 0) {
			/* assume no restrictions on LPM transitions */
			scontrol &= ~(0x7 << 8);
		else {

			/*
			 * If the controller does not support partial, slumber,
			 * or devsleep, then disallow these transitions.
			 */
			if (link->ap->host->flags & ATA_HOST_NO_PART)
				scontrol |= (0x1 << 8);

			if (link->ap->host->flags & ATA_HOST_NO_SSC)
				scontrol |= (0x2 << 8);

			if (link->ap->host->flags & ATA_HOST_NO_DEVSLP)
				scontrol |= (0x4 << 8);
		} else {
			/* empty port, power off */
			scontrol &= ~0xf;
			scontrol |= (0x1 << 2);
Loading