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

Commit d9027470 authored by Gwendal Grignou's avatar Gwendal Grignou Committed by Jeff Garzik
Browse files

[libata] Add ATA transport class



This is a scheleton for libata transport class.
All information is read only, exporting information from libata:
- ata_port class: one per ATA port
- ata_link class: one per ATA port or 15 for SATA Port Multiplier
- ata_device class: up to 2 for PATA link, usually one for SATA.

Signed-off-by: default avatarGwendal Grignou <gwendal@google.com>
Reviewed-by: default avatarGrant Grundler <grundler@google.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent f6f94e2a
Loading
Loading
Loading
Loading
+99 −0
Original line number Diff line number Diff line
What:		/sys/class/ata_...
Date:		August 2008
Contact:	Gwendal Grignou<gwendal@google.com>
Description:

Provide a place in sysfs for storing the ATA topology of the system.  This allows
retrieving various information about ATA objects.

Files under /sys/class/ata_port
-------------------------------

	For each port, a directory ataX is created where X is the ata_port_id of
	the port. The device parent is the ata host device.

idle_irq (read)

	Number of IRQ received by the port while idle [some ata HBA only].

nr_pmp_links (read)

	If a SATA Port Multiplier (PM) is connected, number of link behind it.

Files under /sys/class/ata_link
-------------------------------

	Behind each port, there is a ata_link. If there is a SATA PM in the
	topology, 15 ata_link objects are created.

	If a link is behind a port, the directory name is linkX, where X is
	ata_port_id of the port.
	If a link is behind a PM, its name is linkX.Y where X is ata_port_id
	of the parent port and Y the PM port.

hw_sata_spd_limit

	Maximum speed supported by the connected SATA device.

sata_spd_limit

	Maximum speed imposed by libata.

sata_spd

	Current speed of the link [1.5, 3Gps,...].

Files under /sys/class/ata_device
---------------------------------

	Behind each link, up to two ata device are created.
	The name of the directory is devX[.Y].Z where:
	- X is ata_port_id of the port where the device is connected,
	- Y the port of the PM if any, and
	- Z the device id: for PATA, there is usually 2 devices [0,1],
	only 1 for SATA.

class
	Device class. Can be "ata" for disk, "atapi" for packet device,
	"pmp" for PM, or "none" if no device was found behind the link.

dma_mode

	Transfer modes supported by the device when in DMA mode.
	Mostly used by PATA device.

pio_mode

	Transfer modes supported by the device when in PIO mode.
	Mostly used by PATA device.

xfer_mode

	Current transfer mode.

id

	Cached result of IDENTIFY command, as described in ATA8 7.16 and 7.17.
	Only valid if the device is not a PM.

gscr

	Cached result of the dump of PM GSCR register.
	Valid registers are:
	0: 	SATA_PMP_GSCR_PROD_ID,
	1: 	SATA_PMP_GSCR_REV,
	2: 	SATA_PMP_GSCR_PORT_INFO,
	32:	SATA_PMP_GSCR_ERROR,
	33:	SATA_PMP_GSCR_ERROR_EN,
	64:	SATA_PMP_GSCR_FEAT,
	96:	SATA_PMP_GSCR_FEAT_EN,
	130:	SATA_PMP_GSCR_SII_GPIO
	Only valid if the device is a PM.

spdn_cnt

	Number of time libata decided to lower the speed of link due to errors.

ering

	Formatted output of the error ring of the device.
+1 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
# Should be last libata driver
obj-$(CONFIG_PATA_LEGACY)	+= pata_legacy.o

libata-objs	:= libata-core.o libata-scsi.o libata-eh.o
libata-objs	:= libata-core.o libata-scsi.o libata-eh.o libata-transport.o
libata-$(CONFIG_ATA_SFF)	+= libata-sff.o
libata-$(CONFIG_SATA_PMP)	+= libata-pmp.o
libata-$(CONFIG_ATA_ACPI)	+= libata-acpi.o
+43 −6
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@
#include <linux/ratelimit.h>

#include "libata.h"

#include "libata-transport.h"

/* debounce timing parameters in msecs { interval, duration, timeout } */
const unsigned long sata_deb_timing_normal[]		= {   5,  100, 2000 };
@@ -1017,7 +1017,7 @@ const char *ata_mode_string(unsigned long xfer_mask)
	return "<n/a>";
}

static const char *sata_spd_string(unsigned int spd)
const char *sata_spd_string(unsigned int spd)
{
	static const char * const spd_str[] = {
		"1.5 Gbps",
@@ -5517,7 +5517,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
	int i;

	/* clear everything except for devices */
	memset(link, 0, offsetof(struct ata_link, device[0]));
	memset((void *)link + ATA_LINK_CLEAR_BEGIN, 0,
	       ATA_LINK_CLEAR_END - ATA_LINK_CLEAR_BEGIN);

	link->ap = ap;
	link->pmp = pmp;
@@ -6093,9 +6094,18 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
	for (i = 0; i < host->n_ports; i++)
		host->ports[i]->print_id = ata_print_id++;

	
	/* Create associated sysfs transport objects  */
	for (i = 0; i < host->n_ports; i++) {
		rc = ata_tport_add(host->dev,host->ports[i]);
		if (rc) {
			goto err_tadd;
		}
	}

	rc = ata_scsi_add_hosts(host, sht);
	if (rc)
		return rc;
		goto err_tadd;

	/* associate with ACPI nodes */
	ata_acpi_associate(host);
@@ -6136,6 +6146,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
	}

	return 0;

 err_tadd:
	while (--i >= 0) {
		ata_tport_delete(host->ports[i]);
	}
	return rc;

}

/**
@@ -6226,6 +6243,13 @@ static void ata_port_detach(struct ata_port *ap)
	cancel_rearming_delayed_work(&ap->hotplug_task);

 skip_eh:
	if (ap->pmp_link) {
		int i;
		for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
			ata_tlink_delete(&ap->pmp_link[i]);
	}
	ata_tport_delete(ap);

	/* remove the associated SCSI host */
	scsi_remove_host(ap->scsi_host);
}
@@ -6542,7 +6566,7 @@ static void __init ata_parse_force_param(void)

static int __init ata_init(void)
{
	int rc = -ENOMEM;
	int rc;

	ata_parse_force_param();

@@ -6552,12 +6576,25 @@ static int __init ata_init(void)
		return rc;
	}

	libata_transport_init();
	ata_scsi_transport_template = ata_attach_transport();
	if (!ata_scsi_transport_template) {
		ata_sff_exit();
		rc = -ENOMEM;
		goto err_out;
	}		

	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
	return 0;

err_out:
	return rc;
}

static void __exit ata_exit(void)
{
	ata_release_transport(ata_scsi_transport_template);
	libata_transport_exit();
	ata_sff_exit();
	kfree(ata_force_tbl);
}
+21 −14
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ enum {
	/* error flags */
	ATA_EFLAG_IS_IO			= (1 << 0),
	ATA_EFLAG_DUBIOUS_XFER		= (1 << 1),
	ATA_EFLAG_OLD_ER                = (1 << 31),

	/* error categories */
	ATA_ECAT_NONE			= 0,
@@ -396,12 +397,7 @@ static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
	return NULL;
}

static void ata_ering_clear(struct ata_ering *ering)
{
	memset(ering, 0, sizeof(*ering));
}

static int ata_ering_map(struct ata_ering *ering,
int ata_ering_map(struct ata_ering *ering,
		  int (*map_fn)(struct ata_ering_entry *, void *),
		  void *arg)
{
@@ -422,6 +418,17 @@ static int ata_ering_map(struct ata_ering *ering,
	return rc;
}

int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg)
{
	ent->eflags |= ATA_EFLAG_OLD_ER;
	return 0;
}

static void ata_ering_clear(struct ata_ering *ering)
{
	ata_ering_map(ering, ata_ering_clear_cb, NULL);
}

static unsigned int ata_eh_dev_action(struct ata_device *dev)
{
	struct ata_eh_context *ehc = &dev->link->eh_context;
@@ -1755,7 +1762,7 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
	struct speed_down_verdict_arg *arg = void_arg;
	int cat;

	if (ent->timestamp < arg->since)
	if ((ent->eflags & ATA_EFLAG_OLD_ER) || (ent->timestamp < arg->since))
		return -1;

	cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
+16 −2
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/libata.h>
#include <linux/slab.h>
#include "libata.h"
#include "libata-transport.h"

const struct ata_port_operations sata_pmp_port_ops = {
	.inherits		= &sata_port_ops,
@@ -315,7 +316,7 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
{
	struct ata_link *pmp_link = ap->pmp_link;
	int i;
	int i, err;

	if (!pmp_link) {
		pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS,
@@ -327,6 +328,13 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
			ata_link_init(ap, &pmp_link[i], i);

		ap->pmp_link = pmp_link;

		for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
			err = ata_tlink_add(&pmp_link[i]);
			if (err) {
				goto err_tlink;
			}
		}
	}

	for (i = 0; i < nr_ports; i++) {
@@ -339,6 +347,12 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
	}

	return 0;
  err_tlink:
	while (--i >= 0)
		ata_tlink_delete(&pmp_link[i]);
	kfree(pmp_link);
	ap->pmp_link = NULL;
	return err;
}

static void sata_pmp_quirks(struct ata_port *ap)
Loading