Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f96ed261 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull libata updates from Tejun Heo:
 - Write same support added
 - Minor ahci MSIX irq handling updates
 - Non-critical SCSI command translation fixes
 - Controller specific changes

* 'for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci: qoriq: Revert "ahci: qoriq: Disable NCQ on ls2080a SoC"
  libata: remove <asm-generic/libata-portmap.h>
  libata: remove unused definitions from <asm/libata-portmap.h>
  pata_at91: Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
  ata: Replace BUG() with BUG_ON().
  ata: sata_mv: Replacing dma_pool_alloc and memset with a single call dma_pool_zalloc.
  libata: Some drives failing on SCT Write Same
  ahci: use pci_alloc_irq_vectors
  libata: SCT Write Same handle ATA_DFLAG_PIO
  libata: SCT Write Same / DSM Trim
  libata: Add support for SCT Write Same
  libata: Safely overwrite attached page in WRITE SAME xlat
  ahci: also use a per-port lock for the multi-MSIX case
  ARM: dts: STiH407-family: Add ports-implemented property in sata nodes
  ahci: st: Add ports-implemented property in support
  ahci: qoriq: enable snoopable sata read and write
  ahci: qoriq: adjust sata parameter
  libata-scsi: fix MODE SELECT translation for Control mode page
  libata-scsi: use u8 array to store mode page copy
parents b56061b0 1ce788d2
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -502,10 +502,11 @@
		};

		sata: sata@3200000 {
			compatible = "fsl,ls1043a-ahci", "fsl,ls1021a-ahci";
			compatible = "fsl,ls1043a-ahci";
			reg = <0x0 0x3200000 0x0 0x10000>;
			interrupts = <0 69 0x4>;
			clocks = <&clockgen 4 0>;
			dma-coherent;
		};

		msi1: msi-controller1@1571000 {
+2 −0
Original line number Diff line number Diff line
@@ -683,6 +683,7 @@
			reg = <0x0 0x3200000 0x0 0x10000>;
			interrupts = <0 133 0x4>; /* Level high type */
			clocks = <&clockgen 4 3>;
			dma-coherent;
		};

		sata1: sata@3210000 {
@@ -691,6 +692,7 @@
			reg = <0x0 0x3210000 0x0 0x10000>;
			interrupts = <0 136 0x4>; /* Level high type */
			clocks = <&clockgen 4 3>;
			dma-coherent;
		};

		usb0: usb3@3100000 {
+0 −4
Original line number Diff line number Diff line
#ifndef __ASM_IA64_LIBATA_PORTMAP_H
#define __ASM_IA64_LIBATA_PORTMAP_H

#define ATA_PRIMARY_CMD		0x1F0
#define ATA_PRIMARY_CTL		0x3F6
#define ATA_PRIMARY_IRQ(dev)	isa_irq_to_vector(14)

#define ATA_SECONDARY_CMD	0x170
#define ATA_SECONDARY_CTL	0x376
#define ATA_SECONDARY_IRQ(dev)	isa_irq_to_vector(15)

#endif
+0 −4
Original line number Diff line number Diff line
#ifndef __ASM_POWERPC_LIBATA_PORTMAP_H
#define __ASM_POWERPC_LIBATA_PORTMAP_H

#define ATA_PRIMARY_CMD	0x1F0
#define ATA_PRIMARY_CTL	0x3F6
#define ATA_PRIMARY_IRQ(dev)	pci_get_legacy_ide_irq(dev, 0)

#define ATA_SECONDARY_CMD	0x170
#define ATA_SECONDARY_CTL	0x376
#define ATA_SECONDARY_IRQ(dev)	pci_get_legacy_ide_irq(dev, 1)

#endif
+32 −117
Original line number Diff line number Diff line
@@ -1400,142 +1400,56 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
}
#endif

/*
 * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
 * to single msi.
 */
static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports,
			  struct ahci_host_priv *hpriv, unsigned long flags)
static int ahci_get_irq_vector(struct ata_host *host, int port)
{
	int nvec, i, rc;

	/* Do not init MSI-X if MSI is disabled for the device */
	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
		return -ENODEV;

	nvec = pci_msix_vec_count(pdev);
	if (nvec < 0)
		return nvec;

	/*
	 * Proper MSI-X implementations will have a vector per-port.
	 * Barring that, we prefer single-MSI over single-MSIX.  If this
	 * check fails (not enough MSI-X vectors for all ports) we will
	 * be called again with the flag clear iff ahci_init_msi()
	 * fails.
	 */
	if (flags & AHCI_HFLAG_MULTI_MSIX) {
		if (nvec < n_ports)
			return -ENODEV;
		nvec = n_ports;
	} else if (nvec) {
		nvec = 1;
	} else {
		/*
		 * Emit dev_err() since this was the non-legacy irq
		 * method of last resort.
		 */
		rc = -ENODEV;
		goto fail;
	}

	for (i = 0; i < nvec; i++)
		hpriv->msix[i].entry = i;
	rc = pci_enable_msix_exact(pdev, hpriv->msix, nvec);
	if (rc < 0)
		goto fail;

	if (nvec > 1)
		hpriv->flags |= AHCI_HFLAG_MULTI_MSIX;
	hpriv->irq = hpriv->msix[0].vector; /* for single msi-x */

	return nvec;
fail:
	dev_err(&pdev->dev,
		"failed to enable MSI-X with error %d, # of vectors: %d\n",
		rc, nvec);

	return rc;
	return pci_irq_vector(to_pci_dev(host->dev), port);
}

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

	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
		return -ENODEV;

	nvec = pci_msi_vec_count(pdev);
	if (nvec < 0)
		return nvec;

	/*
	 * If number of MSIs is less than number of ports then Sharing Last
	 * Message mode could be enforced. In this case assume that advantage
	 * of multipe MSIs is negated and use single MSI mode instead.
	 */
	if (nvec < n_ports)
		goto single_msi;

	rc = pci_enable_msi_exact(pdev, nvec);
	if (rc == -ENOSPC)
		goto single_msi;
	if (rc < 0)
		return rc;

	/* fallback to single MSI mode if the controller enforced MRSM mode */
	if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
		pci_disable_msi(pdev);
		printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
		goto single_msi;
	}

	if (nvec > 1)
	nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
			PCI_IRQ_MSIX | PCI_IRQ_MSI);
	if (nvec > 0) {
		if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
			hpriv->get_irq_vector = ahci_get_irq_vector;
			hpriv->flags |= AHCI_HFLAG_MULTI_MSI;

	goto out;

single_msi:
	nvec = 1;

	rc = pci_enable_msi(pdev);
	if (rc < 0)
		return rc;
out:
	hpriv->irq = pdev->irq;

			return nvec;
		}

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

		/*
	 * Try to enable per-port MSI-X.  If the host is not capable
	 * fall back to single MSI before finally attempting single
	 * MSI-X.
		 * Fallback to single MSI mode if the controller enforced MRSM
		 * mode.
		 */
	nvec = ahci_init_msix(pdev, n_ports, hpriv, AHCI_HFLAG_MULTI_MSIX);
	if (nvec >= 0)
		return nvec;
		printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
		pci_free_irq_vectors(pdev);
	}

	nvec = ahci_init_msi(pdev, n_ports, hpriv);
	if (nvec >= 0)
	/*
	 * -ENOSPC indicated we don't have enough vectors.  Don't bother trying
	 * a single vectors for any other error:
	 */
	if (nvec < 0 && nvec != -ENOSPC)
		return nvec;

	/* try single-msix */
	nvec = ahci_init_msix(pdev, n_ports, hpriv, 0);
	if (nvec >= 0)
	/*
	 * If the host is not capable of supporting per-port vectors, fall
	 * back to single MSI before finally attempting single MSI-X.
	 */
	nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
	if (nvec == 1)
		return nvec;

	/* legacy intx interrupts */
	pci_intx(pdev, 1);
	hpriv->irq = pdev->irq;

	return 0;
	return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
}

static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1698,11 +1612,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (!host)
		return -ENOMEM;
	host->private_data = hpriv;
	hpriv->msix = devm_kzalloc(&pdev->dev,
			sizeof(struct msix_entry) * n_ports, GFP_KERNEL);
	if (!hpriv->msix)
		return -ENOMEM;
	ahci_init_interrupts(pdev, n_ports, hpriv);

	if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
		/* legacy intx interrupts */
		pci_intx(pdev, 1);
	}
	hpriv->irq = pdev->irq;

	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
		host->flags |= ATA_HOST_PARALLEL_SCAN;
Loading