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

Commit b92e09bb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull libata updates from Tejun Heo:

 - Adam added opt-in ATA command priority support.

 - There are machines which hide multiple nvme devices behind an ahci
   BAR. Dan Williams proposed a solution to force-switch the mode but
   deemed too hackishd. People are gonna discuss the proper way to
   handle the situation in nvme standard meetings. For now, detect and
   warn about the situation.

 - Low level driver specific changes.

Christoph Hellwig pipes in about the hidden nvme warning:
 "I wish that was the case. We've pretty much agreed that we'll want to
  implement it as a virtual PCIe root bridge, similar to Intels other
  'innovation' VMD that we work around that way.

  But Intel management has apparently decided that they don't want to
  spend more cycles on this now that Lenovo has an optional BIOS that
  doesn't force this broken mode anymore, and no one outside of Intel
  has enough information to implement something like this.

  So for now I guess this warning is it, until Intel reconsideres and
  spends resources on fixing up the damage their Chipset people caused"

* 'for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci: warn about remapped NVMe devices
  ahci-remap.h: add ahci remapping definitions
  nvme: move NVMe class code to pci_ids.h
  pata: imx: support controller modes up to PIO4
  pata: imx: add support of setting timings for PIO modes
  pata: imx: set controller PIO mode with .set_piomode callback
  pata: imx: sort headers out
  ata: set ncq_prio_enabled iff device has support
  ata: ATA Command Priority Disabled By Default
  ata: Enabling ATA Command Priorities
  block: Add iocontext priority to request
  ahci: qoriq: added ls1046a platform support
parents c11a6cfb aecec8b6
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1154,6 +1154,7 @@ static struct request *__get_request(struct request_list *rl, unsigned int op,

	blk_rq_init(q, rq);
	blk_rq_set_rl(rq, rl);
	blk_rq_set_prio(rq, ioc);
	rq->cmd_flags = op;
	rq->rq_flags = rq_flags;

@@ -1626,6 +1627,7 @@ void init_request_from_bio(struct request *req, struct bio *bio)

	req->errors = 0;
	req->__sector = bio->bi_iter.bi_sector;
	if (ioprio_valid(bio_prio(bio)))
		req->ioprio = bio_prio(bio);
	blk_rq_bio_prep(req->q, req, bio);
}
+39 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
#include <linux/ahci-remap.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include "ahci.h"

#define DRV_NAME	"ahci"
@@ -1400,6 +1402,40 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
}
#endif

static void ahci_remap_check(struct pci_dev *pdev, int bar,
		struct ahci_host_priv *hpriv)
{
	int i, count = 0;
	u32 cap;

	/*
	 * Check if this device might have remapped nvme devices.
	 */
	if (pdev->vendor != PCI_VENDOR_ID_INTEL ||
	    pci_resource_len(pdev, bar) < SZ_512K ||
	    bar != AHCI_PCI_BAR_STANDARD ||
	    !(readl(hpriv->mmio + AHCI_VSCAP) & 1))
		return;

	cap = readq(hpriv->mmio + AHCI_REMAP_CAP);
	for (i = 0; i < AHCI_MAX_REMAP; i++) {
		if ((cap & (1 << i)) == 0)
			continue;
		if (readl(hpriv->mmio + ahci_remap_dcc(i))
				!= PCI_CLASS_STORAGE_EXPRESS)
			continue;

		/* We've found a remapped device */
		count++;
	}

	if (!count)
		return;

	dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count);
	dev_warn(&pdev->dev, "Switch your BIOS from RAID to AHCI mode to use them.\n");
}

static int ahci_get_irq_vector(struct ata_host *host, int port)
{
	return pci_irq_vector(to_pci_dev(host->dev), port);
@@ -1541,6 +1577,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)

	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];

	/* detect remapped nvme devices */
	ahci_remap_check(pdev, ahci_pci_bar, hpriv);

	/* must set flag prior to save config in order to take effect */
	if (ahci_broken_devslp(pdev))
		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
+13 −3
Original line number Diff line number Diff line
@@ -46,11 +46,13 @@
#define LS1021A_AXICC_ADDR	0xC0

#define SATA_ECC_DISABLE	0x00020000
#define LS1046A_SATA_ECC_DIS	0x80000000

enum ahci_qoriq_type {
	AHCI_LS1021A,
	AHCI_LS1043A,
	AHCI_LS2080A,
	AHCI_LS1046A,
};

struct ahci_qoriq_priv {
@@ -63,6 +65,7 @@ static const struct of_device_id ahci_qoriq_of_match[] = {
	{ .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A},
	{ .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
	{ .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
	{ .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
	{},
};
MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
@@ -175,6 +178,13 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
		writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
		writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
		break;

	case AHCI_LS1046A:
		writel(LS1046A_SATA_ECC_DIS, qpriv->ecc_addr);
		writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
		writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
		writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
		break;
	}

	return 0;
@@ -204,9 +214,9 @@ static int ahci_qoriq_probe(struct platform_device *pdev)

	qoriq_priv->type = (enum ahci_qoriq_type)of_id->data;

	if (qoriq_priv->type == AHCI_LS1021A) {
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"sata-ecc");
	if (res) {
		qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res);
		if (IS_ERR(qoriq_priv->ecc_addr))
			return PTR_ERR(qoriq_priv->ecc_addr);
+1 −0
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ EXPORT_SYMBOL_GPL(ahci_shost_attrs);
struct device_attribute *ahci_sdev_attrs[] = {
	&dev_attr_sw_activity,
	&dev_attr_unload_heads,
	&dev_attr_ncq_prio_enable,
	NULL
};
EXPORT_SYMBOL_GPL(ahci_sdev_attrs);
+34 −1
Original line number Diff line number Diff line
@@ -739,6 +739,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
 *	@n_block: Number of blocks
 *	@tf_flags: RW/FUA etc...
 *	@tag: tag
 *	@class: IO priority class
 *
 *	LOCKING:
 *	None.
@@ -753,7 +754,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
 */
int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
		    u64 block, u32 n_block, unsigned int tf_flags,
		    unsigned int tag)
		    unsigned int tag, int class)
{
	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
	tf->flags |= tf_flags;
@@ -785,6 +786,12 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
		tf->device = ATA_LBA;
		if (tf->flags & ATA_TFLAG_FUA)
			tf->device |= 1 << 7;

		if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE) {
			if (class == IOPRIO_CLASS_RT)
				tf->hob_nsect |= ATA_PRIO_HIGH <<
						 ATA_SHIFT_PRIO;
		}
	} else if (dev->flags & ATA_DFLAG_LBA) {
		tf->flags |= ATA_TFLAG_LBA;

@@ -2156,6 +2163,30 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev)
	}
}

static void ata_dev_config_ncq_prio(struct ata_device *dev)
{
	struct ata_port *ap = dev->link->ap;
	unsigned int err_mask;

	err_mask = ata_read_log_page(dev,
				     ATA_LOG_SATA_ID_DEV_DATA,
				     ATA_LOG_SATA_SETTINGS,
				     ap->sector_buf,
				     1);
	if (err_mask) {
		ata_dev_dbg(dev,
			    "failed to get Identify Device data, Emask 0x%x\n",
			    err_mask);
		return;
	}

	if (ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET] & BIT(3))
		dev->flags |= ATA_DFLAG_NCQ_PRIO;
	else
		ata_dev_dbg(dev, "SATA page does not support priority\n");

}

static int ata_dev_config_ncq(struct ata_device *dev,
			       char *desc, size_t desc_sz)
{
@@ -2205,6 +2236,8 @@ static int ata_dev_config_ncq(struct ata_device *dev,
			ata_dev_config_ncq_send_recv(dev);
		if (ata_id_has_ncq_non_data(dev->id))
			ata_dev_config_ncq_non_data(dev);
		if (ata_id_has_ncq_prio(dev->id))
			ata_dev_config_ncq_prio(dev);
	}

	return 0;
Loading