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

Commit 357397a1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull libata changes from Tejun Heo:
 "Two interesting changes.

   - libata acpi handling has been restructured so that the association
     between ata devices and ACPI handles are less convoluted.  This
     change shouldn't change visible behavior.

   - Queued TRIM support, which enables sending TRIM to the device
     without draining in-flight RW commands, is added.  Currently only
     enabled for ahci (and likely to stay that way for the foreseeable
     future).

  Other changes are driver-specific updates / fixes"

* 'for-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  libata: bugfix: Remove __le32 in ata_tf_to_fis()
  libata: acpi: Remove ata_dev_acpi_handle stub in libata.h
  libata: Add support for queued DSM TRIM
  libata: Add support for SEND/RECEIVE FPDMA QUEUED
  libata: Add H2D FIS "auxiliary" port flag
  libata: Populate host-to-device FIS "auxiliary" field
  ata: acpi: rework the ata acpi bind support
  sata, highbank: send extra clock cycles in SGPIO patterns
  sata, highbank: set tx_atten override bits
  devicetree: create a separate binding description for sata_highbank
  drivers/ata/sata_rcar.c: simplify use of devm_ioremap_resource
  sata highbank: enable 64-bit DMA mask when using LPAE
  ata: pata_samsung_cf: add missing __iomem annotation
  ata: pata_arasan: Staticize local symbols
  sata_mv: Remove unneeded CONFIG_HAVE_CLK ifdefs
  ata: use dev_get_platdata()
  sata_mv: Remove unneeded forward declaration
  libata: acpi: remove dead code for ata_acpi_(un)bind
  libata: move 'struct ata_taskfile' and friends from ata.h to libata.h
parents 9ee52a16 86a565e6
Loading
Loading
Loading
Loading
+4 −14
Original line number Diff line number Diff line
@@ -4,27 +4,17 @@ SATA nodes are defined to describe on-chip Serial ATA controllers.
Each SATA controller should have its own node.

Required properties:
- compatible        : compatible list, contains "calxeda,hb-ahci" or "snps,spear-ahci"
- compatible        : compatible list, contains "snps,spear-ahci"
- interrupts        : <interrupt mapping for SATA IRQ>
- reg               : <registers mapping>

Optional properties:
- calxeda,port-phys: phandle-combophy and lane assignment, which maps each
			SATA port to a combophy and a lane within that
			combophy
- calxeda,sgpio-gpio: phandle-gpio bank, bit offset, and default on or off,
			which indicates that the driver supports SGPIO
			indicator lights using the indicated GPIOs
- calxeda,led-order : a u32 array that map port numbers to offsets within the
			SGPIO bitstream.
- dma-coherent      : Present if dma operations are coherent

Example:
        sata@ffe08000 {
		compatible = "calxeda,hb-ahci";
		compatible = "snps,spear-ahci";
		reg = <0xffe08000 0x1000>;
		interrupts = <115>;
		calxeda,port-phys = <&combophy5 0 &combophy0 0 &combophy0 1
					&combophy0 2 &combophy0 3>;

        };
+44 −0
Original line number Diff line number Diff line
* Calxeda AHCI SATA Controller

SATA nodes are defined to describe on-chip Serial ATA controllers.
The Calxeda SATA controller mostly conforms to the AHCI interface
with some special extensions to add functionality.
Each SATA controller should have its own node.

Required properties:
- compatible        : compatible list, contains "calxeda,hb-ahci"
- interrupts        : <interrupt mapping for SATA IRQ>
- reg               : <registers mapping>

Optional properties:
- dma-coherent      : Present if dma operations are coherent
- calxeda,port-phys : phandle-combophy and lane assignment, which maps each
			SATA port to a combophy and a lane within that
			combophy
- calxeda,sgpio-gpio: phandle-gpio bank, bit offset, and default on or off,
			which indicates that the driver supports SGPIO
			indicator lights using the indicated GPIOs
- calxeda,led-order : a u32 array that map port numbers to offsets within the
			SGPIO bitstream.
- calxeda,tx-atten  : a u32 array that contains TX attenuation override
			codes, one per port. The upper 3 bytes are always
			0 and thus ignored.
- calxeda,pre-clocks : a u32 that indicates the number of additional clock
			cycles to transmit before sending an SGPIO pattern
- calxeda,post-clocks: a u32 that indicates the number of additional clock
			cycles to transmit after sending an SGPIO pattern

Example:
        sata@ffe08000 {
		compatible = "calxeda,hb-ahci";
		reg = <0xffe08000 0x1000>;
		interrupts = <115>;
		dma-coherent;
		calxeda,port-phys = <&combophy5 0 &combophy0 0 &combophy0 1
					&combophy0 2 &combophy0 3>;
		calxeda,sgpio-gpio =<&gpioh 5 1 &gpioh 6 1 &gpioh 7 1>;
		calxeda,led-order = <4 0 1 2 3>;
		calxeda,tx-atten = <0xff 22 0xff 0xff 23>;
		calxeda,pre-clocks = <10>;
		calxeda,post-clocks = <0>;
        };
+8 −0
Original line number Diff line number Diff line
@@ -1295,6 +1295,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
		 */
		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
			pi.flags |= ATA_FLAG_FPDMA_AA;

		/*
		 * All AHCI controllers should be forward-compatible
		 * with the new auxiliary field. This code should be
		 * conditionalized if any buggy AHCI controllers are
		 * encountered.
		 */
		pi.flags |= ATA_FLAG_FPDMA_AUX;
	}

	if (hpriv->cap & HOST_CAP_PMP)
+79 −199
Original line number Diff line number Diff line
@@ -34,62 +34,25 @@ struct ata_acpi_gtf {
	u8	tf[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
} __packed;

/*
 *	Helper - belongs in the PCI layer somewhere eventually
 */
static int is_pci_dev(struct device *dev)
{
	return (dev->bus == &pci_bus_type);
}

static void ata_acpi_clear_gtf(struct ata_device *dev)
{
	kfree(dev->gtf_cache);
	dev->gtf_cache = NULL;
}

/**
 * ata_ap_acpi_handle - provide the acpi_handle for an ata_port
 * @ap: the acpi_handle returned will correspond to this port
 *
 * Returns the acpi_handle for the ACPI namespace object corresponding to
 * the ata_port passed into the function, or NULL if no such object exists
 */
acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
{
	if (ap->flags & ATA_FLAG_ACPI_SATA)
		return NULL;

	return ap->scsi_host ?
		DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev) : NULL;
}
EXPORT_SYMBOL(ata_ap_acpi_handle);

/**
 * ata_dev_acpi_handle - provide the acpi_handle for an ata_device
 * @dev: the acpi_device returned will correspond to this port
 * @dev: the acpi_handle returned will correspond to this device
 *
 * Returns the acpi_handle for the ACPI namespace object corresponding to
 * the ata_device passed into the function, or NULL if no such object exists
 * or ACPI is disabled for this device due to consecutive errors.
 */
acpi_handle ata_dev_acpi_handle(struct ata_device *dev)
{
	acpi_integer adr;
	struct ata_port *ap = dev->link->ap;

	if (libata_noacpi || dev->flags & ATA_DFLAG_ACPI_DISABLED)
		return NULL;

	if (ap->flags & ATA_FLAG_ACPI_SATA) {
		if (!sata_pmp_attached(ap))
			adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
		else
			adr = SATA_ADR(ap->port_no, dev->link->pmp);
		return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), adr);
	} else
		return acpi_get_child(ata_ap_acpi_handle(ap), dev->devno);
	return dev->flags & ATA_DFLAG_ACPI_DISABLED ?
			NULL : ACPI_HANDLE(&dev->tdev);
}
EXPORT_SYMBOL(ata_dev_acpi_handle);

/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
@@ -156,10 +119,8 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,

	spin_unlock_irqrestore(ap->lock, flags);

	if (wait) {
	if (wait)
		ata_port_wait_eh(ap);
		flush_work(&ap->hotplug_task.work);
	}
}

static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
@@ -216,37 +177,55 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
	.uevent = ata_acpi_ap_uevent,
};

void ata_acpi_hotplug_init(struct ata_host *host)
/* bind acpi handle to pata port */
void ata_acpi_bind_port(struct ata_port *ap)
{
	int i;
	acpi_handle host_handle = ACPI_HANDLE(ap->host->dev);

	for (i = 0; i < host->n_ports; i++) {
		struct ata_port *ap = host->ports[i];
		acpi_handle handle;
		struct ata_device *dev;
	if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_handle)
		return;

		if (!ap)
			continue;
	ACPI_HANDLE_SET(&ap->tdev, acpi_get_child(host_handle, ap->port_no));

	if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;

		handle = ata_ap_acpi_handle(ap);
		if (handle) {
	/* we might be on a docking station */
			register_hotplug_dock_device(handle,
						     &ata_acpi_ap_dock_ops, ap,
						     NULL, NULL);
	register_hotplug_dock_device(ACPI_HANDLE(&ap->tdev),
				     &ata_acpi_ap_dock_ops, ap, NULL, NULL);
}

		ata_for_each_dev(dev, &ap->link, ALL) {
			handle = ata_dev_acpi_handle(dev);
			if (!handle)
				continue;
void ata_acpi_bind_dev(struct ata_device *dev)
{
	struct ata_port *ap = dev->link->ap;
	acpi_handle port_handle = ACPI_HANDLE(&ap->tdev);
	acpi_handle host_handle = ACPI_HANDLE(ap->host->dev);
	acpi_handle parent_handle;
	u64 adr;

			/* we might be on a docking station */
			register_hotplug_dock_device(handle,
						     &ata_acpi_dev_dock_ops,
						     dev, NULL, NULL);
		}
	/*
	 * For both sata/pata devices, host handle is required.
	 * For pata device, port handle is also required.
	 */
	if (libata_noacpi || !host_handle ||
			(!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_handle))
		return;

	if (ap->flags & ATA_FLAG_ACPI_SATA) {
		if (!sata_pmp_attached(ap))
			adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
		else
			adr = SATA_ADR(ap->port_no, dev->link->pmp);
		parent_handle = host_handle;
	} else {
		adr = dev->devno;
		parent_handle = port_handle;
	}

	ACPI_HANDLE_SET(&dev->tdev, acpi_get_child(parent_handle, adr));

	register_hotplug_dock_device(ata_dev_acpi_handle(dev),
				     &ata_acpi_dev_dock_ops, dev, NULL, NULL);
}

/**
@@ -270,18 +249,34 @@ void ata_acpi_dissociate(struct ata_host *host)
		struct ata_port *ap = host->ports[i];
		const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);

		if (ata_ap_acpi_handle(ap) && gtm)
		if (ACPI_HANDLE(&ap->tdev) && gtm)
			ata_acpi_stm(ap, gtm);
	}
}

static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle,
			  struct ata_acpi_gtm *gtm)
/**
 * ata_acpi_gtm - execute _GTM
 * @ap: target ATA port
 * @gtm: out parameter for _GTM result
 *
 * Evaluate _GTM and store the result in @gtm.
 *
 * LOCKING:
 * EH context.
 *
 * RETURNS:
 * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
 */
int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
{
	struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
	union acpi_object *out_obj;
	acpi_status status;
	int rc = 0;
	acpi_handle handle = ACPI_HANDLE(&ap->tdev);

	if (!handle)
		return -EINVAL;

	status = acpi_evaluate_object(handle, "_GTM", NULL, &output);

@@ -317,27 +312,6 @@ static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle,
	return rc;
}

/**
 * ata_acpi_gtm - execute _GTM
 * @ap: target ATA port
 * @gtm: out parameter for _GTM result
 *
 * Evaluate _GTM and store the result in @gtm.
 *
 * LOCKING:
 * EH context.
 *
 * RETURNS:
 * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
 */
int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
{
	if (ata_ap_acpi_handle(ap))
		return __ata_acpi_gtm(ap, ata_ap_acpi_handle(ap), gtm);
	else
		return -EINVAL;
}

EXPORT_SYMBOL_GPL(ata_acpi_gtm);

/**
@@ -374,8 +348,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm)
	input.count = 3;
	input.pointer = in_params;

	status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_STM", &input,
				      NULL);
	status = acpi_evaluate_object(ACPI_HANDLE(&ap->tdev), "_STM",
				      &input, NULL);

	if (status == AE_NOT_FOUND)
		return -ENOENT;
@@ -850,7 +824,7 @@ void ata_acpi_on_resume(struct ata_port *ap)
	const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
	struct ata_device *dev;

	if (ata_ap_acpi_handle(ap) && gtm) {
	if (ACPI_HANDLE(&ap->tdev) && gtm) {
		/* _GTM valid */

		/* restore timing parameters */
@@ -894,8 +868,7 @@ static int ata_acpi_choose_suspend_state(struct ata_device *dev, bool runtime)
		d_max_in = ACPI_STATE_D3_HOT;

out:
	return acpi_pm_device_sleep_state(&dev->sdev->sdev_gendev,
					  NULL, d_max_in);
	return acpi_pm_device_sleep_state(&dev->tdev, NULL, d_max_in);
}

static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state)
@@ -932,7 +905,7 @@ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state)
	struct ata_device *dev;
	acpi_handle port_handle;

	port_handle = ata_ap_acpi_handle(ap);
	port_handle = ACPI_HANDLE(&ap->tdev);
	if (!port_handle)
		return;

@@ -1063,109 +1036,16 @@ void ata_acpi_on_disable(struct ata_device *dev)
	ata_acpi_clear_gtf(dev);
}

static int compat_pci_ata(struct ata_port *ap)
{
	struct device *dev = ap->tdev.parent;
	struct pci_dev *pdev;

	if (!is_pci_dev(dev))
		return 0;

	pdev = to_pci_dev(dev);

	if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
	    (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
		return 0;

	return 1;
}

static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle)
{
	if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA)
		return -ENODEV;

	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(ap->tdev.parent),
			ap->port_no);

	if (!*handle)
		return -ENODEV;

	if (__ata_acpi_gtm(ap, *handle, &ap->__acpi_init_gtm) == 0)
		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;

	return 0;
}

static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
				acpi_handle *handle)
{
	struct ata_device *ata_dev;

	if (ap->flags & ATA_FLAG_ACPI_SATA) {
		if (!sata_pmp_attached(ap))
			ata_dev = &ap->link.device[sdev->id];
		else
			ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
	}
	else {
		ata_dev = &ap->link.device[sdev->id];
	}

	*handle = ata_dev_acpi_handle(ata_dev);

	if (!*handle)
		return -ENODEV;

	return 0;
}

static int is_ata_port(const struct device *dev)
{
	return dev->type == &ata_port_type;
}

static struct ata_port *dev_to_ata_port(struct device *dev)
{
	while (!is_ata_port(dev)) {
		if (!dev->parent)
			return NULL;
		dev = dev->parent;
	}
	return to_ata_port(dev);
}

static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
{
	struct ata_port *ap = dev_to_ata_port(dev);

	if (!ap)
		return -ENODEV;

	if (!compat_pci_ata(ap))
		return -ENODEV;

	if (scsi_is_host_device(dev))
		return ata_acpi_bind_host(ap, handle);
	else if (scsi_is_sdev_device(dev)) {
		struct scsi_device *sdev = to_scsi_device(dev);

		return ata_acpi_bind_device(ap, sdev, handle);
	} else
		return -ENODEV;
}

static struct acpi_bus_type ata_acpi_bus = {
	.name = "ATA",
	.find_device = ata_acpi_find_device,
};

int ata_acpi_register(void)
void ata_scsi_acpi_bind(struct ata_device *dev)
{
	return scsi_register_acpi_bus_type(&ata_acpi_bus);
	acpi_handle handle = ata_dev_acpi_handle(dev);
	if (handle)
		acpi_dev_pm_add_dependent(handle, &dev->sdev->sdev_gendev);
}

void ata_acpi_unregister(void)
void ata_scsi_acpi_unbind(struct ata_device *dev)
{
	scsi_unregister_acpi_bus_type(&ata_acpi_bus);
	acpi_handle handle = ata_dev_acpi_handle(dev);
	if (handle)
		acpi_dev_pm_remove_dependent(handle, &dev->sdev->sdev_gendev);
}
+20 −9
Original line number Diff line number Diff line
@@ -569,10 +569,10 @@ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis)
	fis[14] = 0;
	fis[15] = tf->ctl;

	fis[16] = 0;
	fis[17] = 0;
	fis[18] = 0;
	fis[19] = 0;
	fis[16] = tf->auxiliary & 0xff;
	fis[17] = (tf->auxiliary >> 8) & 0xff;
	fis[18] = (tf->auxiliary >> 16) & 0xff;
	fis[19] = (tf->auxiliary >> 24) & 0xff;
}

/**
@@ -2139,6 +2139,22 @@ static int ata_dev_config_ncq(struct ata_device *dev,
	else
		snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth,
			ddepth, aa_desc);

	if ((ap->flags & ATA_FLAG_FPDMA_AUX) &&
	    ata_id_has_ncq_send_and_recv(dev->id)) {
		err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV,
					     0, ap->sector_buf, 1);
		if (err_mask) {
			ata_dev_dbg(dev,
				    "failed to get NCQ Send/Recv Log Emask 0x%x\n",
				    err_mask);
		} else {
			dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
			memcpy(dev->ncq_send_recv_cmds, ap->sector_buf,
				ATA_LOG_NCQ_SEND_RECV_SIZE);
		}
	}

	return 0;
}

@@ -6150,8 +6166,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
	if (rc)
		goto err_tadd;

	ata_acpi_hotplug_init(host);

	/* set cable, sata_spd_limit and report */
	for (i = 0; i < host->n_ports; i++) {
		struct ata_port *ap = host->ports[i];
@@ -6632,8 +6646,6 @@ static int __init ata_init(void)

	ata_parse_force_param();

	ata_acpi_register();

	rc = ata_sff_init();
	if (rc) {
		kfree(ata_force_tbl);
@@ -6660,7 +6672,6 @@ static void __exit ata_exit(void)
	ata_release_transport(ata_scsi_transport_template);
	libata_transport_exit();
	ata_sff_exit();
	ata_acpi_unregister();
	kfree(ata_force_tbl);
}

Loading