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

Commit 82219fce authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'upstream-2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  ata_piix: IDE Mode SATA patch for Intel Ibex Peak DeviceIDs
  libata-eh: clear UNIT ATTENTION after reset
  ata_piix: add Hercules EC-900 mini-notebook to ich_laptop short cable list
  libata: reorder ata_device to remove 8 bytes of padding on 64 bits
  [libata] pata_bf54x: Add proper PM operation
  pata_sil680: convert CONFIG_PPC_MERGE to CONFIG_PPC
  libata: Implement disk shock protection support
  [libata] Introduce ata_id_has_unload()
  PATA: RPC now selects HAVE_PATA_PLATFORM for pata platform driver
  ata_piix: drop merged SCR access and use slave_link instead
  libata: implement slave_link
  libata: misc updates to prepare for slave link
  libata: reimplement link iterator
  libata: make SCR access ops per-link
parents 3fa8749e 0395e61b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -663,7 +663,7 @@ config HAVE_PATA_PLATFORM

config PATA_PLATFORM
	tristate "Generic platform device PATA support"
	depends on EMBEDDED || ARCH_RPC || PPC || HAVE_PATA_PLATFORM
	depends on EMBEDDED || PPC || HAVE_PATA_PLATFORM
	help
	  This option enables support for generic directly connected ATA
	  devices commonly found on embedded systems.
+13 −12
Original line number Diff line number Diff line
@@ -267,8 +267,8 @@ struct ahci_port_priv {
					 	 * per PM slot */
};

static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
@@ -316,6 +316,7 @@ static struct device_attribute *ahci_shost_attrs[] = {

static struct device_attribute *ahci_sdev_attrs[] = {
	&dev_attr_sw_activity,
	&dev_attr_unload_heads,
	NULL
};

@@ -820,10 +821,10 @@ static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
	return 0;
}

static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
{
	void __iomem *port_mmio = ahci_port_base(ap);
	int offset = ahci_scr_offset(ap, sc_reg);
	void __iomem *port_mmio = ahci_port_base(link->ap);
	int offset = ahci_scr_offset(link->ap, sc_reg);

	if (offset) {
		*val = readl(port_mmio + offset);
@@ -832,10 +833,10 @@ static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
	return -EINVAL;
}

static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
{
	void __iomem *port_mmio = ahci_port_base(ap);
	int offset = ahci_scr_offset(ap, sc_reg);
	void __iomem *port_mmio = ahci_port_base(link->ap);
	int offset = ahci_scr_offset(link->ap, sc_reg);

	if (offset) {
		writel(val, port_mmio + offset);
@@ -973,7 +974,7 @@ static void ahci_disable_alpm(struct ata_port *ap)
	writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);

	/* go ahead and clean out PhyRdy Change from Serror too */
	ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
	ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));

	/*
 	 * Clear flag to indicate that we should ignore all PhyRdy
@@ -1937,8 +1938,8 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
	ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);

	/* AHCI needs SError cleared; otherwise, it might lock up */
	ahci_scr_read(ap, SCR_ERROR, &serror);
	ahci_scr_write(ap, SCR_ERROR, serror);
	ahci_scr_read(&ap->link, SCR_ERROR, &serror);
	ahci_scr_write(&ap->link, SCR_ERROR, serror);
	host_ehi->serror |= serror;

	/* some controllers set IRQ_IF_ERR on device errors, ignore it */
@@ -2027,7 +2028,7 @@ static void ahci_port_intr(struct ata_port *ap)
	if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
		(status & PORT_IRQ_PHYRDY)) {
		status &= ~PORT_IRQ_PHYRDY;
		ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
		ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
	}

	if (unlikely(status & PORT_IRQ_ERROR)) {
+54 −130
Original line number Diff line number Diff line
@@ -165,8 +165,10 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int ich_pata_cable_detect(struct ata_port *ap);
static u8 piix_vmw_bmdma_status(struct ata_port *ap);
static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
static int piix_sidpr_scr_read(struct ata_link *link,
			       unsigned int reg, u32 *val);
static int piix_sidpr_scr_write(struct ata_link *link,
				unsigned int reg, u32 val);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -278,12 +280,15 @@ static const struct pci_device_id piix_pci_tbl[] = {
	/* SATA Controller IDE (PCH) */
	{ 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
	/* SATA Controller IDE (PCH) */
	{ 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
	/* SATA Controller IDE (PCH) */
	{ 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
	/* SATA Controller IDE (PCH) */
	{ 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
	/* SATA Controller IDE (PCH) */
	{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
	/* SATA Controller IDE (PCH) */
	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },

	{ }	/* terminate list */
};

@@ -582,6 +587,7 @@ static const struct ich_laptop ich_laptop[] = {
	{ 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */
	{ 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */
	{ 0x27DF, 0x103C, 0x30A1 },	/* ICH7 on HP Compaq nc2400 */
	{ 0x27DF, 0x1071, 0xD221 },	/* ICH7 on Hercules EC-900 */
	{ 0x24CA, 0x1025, 0x0061 },	/* ICH4 on ACER Aspire 2023WLMi */
	{ 0x24CA, 0x1025, 0x003d },	/* ICH4 on ACER TM290 */
	{ 0x266F, 0x1025, 0x0066 },	/* ICH6 on ACER Aspire 1694WLMi */
@@ -885,23 +891,9 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 * Serial ATA Index/Data Pair Superset Registers access
 *
 * Beginning from ICH8, there's a sane way to access SCRs using index
 * and data register pair located at BAR5.  This creates an
 * interesting problem of mapping two SCRs to one port.
 *
 * Although they have separate SCRs, the master and slave aren't
 * independent enough to be treated as separate links - e.g. softreset
 * resets both.  Also, there's no protocol defined for hard resetting
 * singled device sharing the virtual port (no defined way to acquire
 * device signature).  This is worked around by merging the SCR values
 * into one sensible value and requesting follow-up SRST after
 * hardreset.
 *
 * SCR merging is perfomed in nibbles which is the unit contents in
 * SCRs are organized.  If two values are equal, the value is used.
 * When they differ, merge table which lists precedence of possible
 * values is consulted and the first match or the last entry when
 * nothing matches is used.  When there's no merge table for the
 * specific nibble, value from the first port is used.
 * and data register pair located at BAR5 which means that we have
 * separate SCRs for master and slave.  This is handled using libata
 * slave_link facility.
 */
static const int piix_sidx_map[] = {
	[SCR_STATUS]	= 0,
@@ -909,120 +901,38 @@ static const int piix_sidx_map[] = {
	[SCR_CONTROL]	= 1,
};

static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
static void piix_sidpr_sel(struct ata_link *link, unsigned int reg)
{
	struct ata_port *ap = dev->link->ap;
	struct ata_port *ap = link->ap;
	struct piix_host_priv *hpriv = ap->host->private_data;

	iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
	iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg],
		  hpriv->sidpr + PIIX_SIDPR_IDX);
}

static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
static int piix_sidpr_scr_read(struct ata_link *link,
			       unsigned int reg, u32 *val)
{
	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;

	piix_sidpr_sel(dev, reg);
	return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
}

static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
{
	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;

	piix_sidpr_sel(dev, reg);
	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
}

static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
{
	u32 val = 0;
	int i, mi;

	for (i = 0, mi = 0; i < 32 / 4; i++) {
		u8 c0 = (val0 >> (i * 4)) & 0xf;
		u8 c1 = (val1 >> (i * 4)) & 0xf;
		u8 merged = c0;
		const int *cur;

		/* if no merge preference, assume the first value */
		cur = merge_tbl[mi];
		if (!cur)
			goto done;
		mi++;

		/* if two values equal, use it */
		if (c0 == c1)
			goto done;

		/* choose the first match or the last from the merge table */
		while (*cur != -1) {
			if (c0 == *cur || c1 == *cur)
				break;
			cur++;
		}
		if (*cur == -1)
			cur--;
		merged = *cur;
	done:
		val |= merged << (i * 4);
	}

	return val;
}

static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
{
	const int * const sstatus_merge_tbl[] = {
		/* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
		/* SPD */ (const int []){ 2, 1, 0, -1 },
		/* IPM */ (const int []){ 6, 2, 1, 0, -1 },
		NULL,
	};
	const int * const scontrol_merge_tbl[] = {
		/* DET */ (const int []){ 1, 0, 4, 0, -1 },
		/* SPD */ (const int []){ 0, 2, 1, 0, -1 },
		/* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
		NULL,
	};
	u32 v0, v1;
	struct piix_host_priv *hpriv = link->ap->host->private_data;

	if (reg >= ARRAY_SIZE(piix_sidx_map))
		return -EINVAL;

	if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
		*val = piix_sidpr_read(&ap->link.device[0], reg);
		return 0;
	}

	v0 = piix_sidpr_read(&ap->link.device[0], reg);
	v1 = piix_sidpr_read(&ap->link.device[1], reg);

	switch (reg) {
	case SCR_STATUS:
		*val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
		break;
	case SCR_ERROR:
		*val = v0 | v1;
		break;
	case SCR_CONTROL:
		*val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
		break;
	}

	piix_sidpr_sel(link, reg);
	*val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
	return 0;
}

static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
static int piix_sidpr_scr_write(struct ata_link *link,
				unsigned int reg, u32 val)
{
	struct piix_host_priv *hpriv = link->ap->host->private_data;

	if (reg >= ARRAY_SIZE(piix_sidx_map))
		return -EINVAL;

	piix_sidpr_write(&ap->link.device[0], reg, val);

	if (ap->flags & ATA_FLAG_SLAVE_POSS)
		piix_sidpr_write(&ap->link.device[1], reg, val);

	piix_sidpr_sel(link, reg);
	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
	return 0;
}

@@ -1363,28 +1273,28 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
	return map;
}

static void __devinit piix_init_sidpr(struct ata_host *host)
static int __devinit piix_init_sidpr(struct ata_host *host)
{
	struct pci_dev *pdev = to_pci_dev(host->dev);
	struct piix_host_priv *hpriv = host->private_data;
	struct ata_device *dev0 = &host->ports[0]->link.device[0];
	struct ata_link *link0 = &host->ports[0]->link;
	u32 scontrol;
	int i;
	int i, rc;

	/* check for availability */
	for (i = 0; i < 4; i++)
		if (hpriv->map[i] == IDE)
			return;
			return 0;

	if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
		return;
		return 0;

	if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
	    pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
		return;
		return 0;

	if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
		return;
		return 0;

	hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];

@@ -1392,7 +1302,7 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
	 * Give it a test drive by inhibiting power save modes which
	 * we'll do anyway.
	 */
	scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
	piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);

	/* if IPM is already 3, SCR access is probably working.  Don't
	 * un-inhibit power save modes as BIOS might have inhibited
@@ -1400,18 +1310,30 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
	 */
	if ((scontrol & 0xf00) != 0x300) {
		scontrol |= 0x300;
		piix_sidpr_write(dev0, SCR_CONTROL, scontrol);
		scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
		piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol);
		piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);

		if ((scontrol & 0xf00) != 0x300) {
			dev_printk(KERN_INFO, host->dev, "SCR access via "
				   "SIDPR is available but doesn't work\n");
			return;
			return 0;
		}
	}

	/* okay, SCRs available, set ops and ask libata for slave_link */
	for (i = 0; i < 2; i++) {
		struct ata_port *ap = host->ports[i];

		ap->ops = &piix_sidpr_sata_ops;

		if (ap->flags & ATA_FLAG_SLAVE_POSS) {
			rc = ata_slave_link_init(ap);
			if (rc)
				return rc;
		}
	}

	host->ports[0]->ops = &piix_sidpr_sata_ops;
	host->ports[1]->ops = &piix_sidpr_sata_ops;
	return 0;
}

static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
@@ -1521,7 +1443,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
	/* initialize controller */
	if (port_flags & ATA_FLAG_SATA) {
		piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
		piix_init_sidpr(host);
		rc = piix_init_sidpr(host);
		if (rc)
			return rc;
	}

	/* apply IOCFG bit18 quirk */
+217 −35
Original line number Diff line number Diff line
@@ -163,6 +163,67 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);


/*
 * Iterator helpers.  Don't use directly.
 *
 * LOCKING:
 * Host lock or EH context.
 */
struct ata_link *__ata_port_next_link(struct ata_port *ap,
				      struct ata_link *link, bool dev_only)
{
	/* NULL link indicates start of iteration */
	if (!link) {
		if (dev_only && sata_pmp_attached(ap))
			return ap->pmp_link;
		return &ap->link;
	}

	/* we just iterated over the host master link, what's next? */
	if (link == &ap->link) {
		if (!sata_pmp_attached(ap)) {
			if (unlikely(ap->slave_link) && !dev_only)
				return ap->slave_link;
			return NULL;
		}
		return ap->pmp_link;
	}

	/* slave_link excludes PMP */
	if (unlikely(link == ap->slave_link))
		return NULL;

	/* iterate to the next PMP link */
	if (++link < ap->pmp_link + ap->nr_pmp_links)
		return link;
	return NULL;
}

/**
 *	ata_dev_phys_link - find physical link for a device
 *	@dev: ATA device to look up physical link for
 *
 *	Look up physical link which @dev is attached to.  Note that
 *	this is different from @dev->link only when @dev is on slave
 *	link.  For all other cases, it's the same as @dev->link.
 *
 *	LOCKING:
 *	Don't care.
 *
 *	RETURNS:
 *	Pointer to the found physical link.
 */
struct ata_link *ata_dev_phys_link(struct ata_device *dev)
{
	struct ata_port *ap = dev->link->ap;

	if (!ap->slave_link)
		return dev->link;
	if (!dev->devno)
		return &ap->link;
	return ap->slave_link;
}

/**
 *	ata_force_cbl - force cable type according to libata.force
 *	@ap: ATA port of interest
@@ -206,7 +267,8 @@ void ata_force_cbl(struct ata_port *ap)
 *	the host link and all fan-out ports connected via PMP.  If the
 *	device part is specified as 0 (e.g. 1.00:), it specifies the
 *	first fan-out link not the host link.  Device number 15 always
 *	points to the host link whether PMP is attached or not.
 *	points to the host link whether PMP is attached or not.  If the
 *	controller has slave link, device number 16 points to it.
 *
 *	LOCKING:
 *	EH context.
@@ -214,12 +276,11 @@ void ata_force_cbl(struct ata_port *ap)
static void ata_force_link_limits(struct ata_link *link)
{
	bool did_spd = false;
	int linkno, i;
	int linkno = link->pmp;
	int i;

	if (ata_is_host_link(link))
		linkno = 15;
	else
		linkno = link->pmp;
		linkno += 15;

	for (i = ata_force_tbl_size - 1; i >= 0; i--) {
		const struct ata_force_ent *fe = &ata_force_tbl[i];
@@ -266,9 +327,9 @@ static void ata_force_xfermask(struct ata_device *dev)
	int alt_devno = devno;
	int i;

	/* allow n.15 for the first device attached to host port */
	if (ata_is_host_link(dev->link) && devno == 0)
		alt_devno = 15;
	/* allow n.15/16 for devices attached to host port */
	if (ata_is_host_link(dev->link))
		alt_devno += 15;

	for (i = ata_force_tbl_size - 1; i >= 0; i--) {
		const struct ata_force_ent *fe = &ata_force_tbl[i];
@@ -320,9 +381,9 @@ static void ata_force_horkage(struct ata_device *dev)
	int alt_devno = devno;
	int i;

	/* allow n.15 for the first device attached to host port */
	if (ata_is_host_link(dev->link) && devno == 0)
		alt_devno = 15;
	/* allow n.15/16 for devices attached to host port */
	if (ata_is_host_link(dev->link))
		alt_devno += 15;

	for (i = 0; i < ata_force_tbl_size; i++) {
		const struct ata_force_ent *fe = &ata_force_tbl[i];
@@ -2681,7 +2742,7 @@ static void sata_print_link_status(struct ata_link *link)
		return;
	sata_scr_read(link, SCR_CONTROL, &scontrol);

	if (ata_link_online(link)) {
	if (ata_phys_link_online(link)) {
		tmp = (sstatus >> 4) & 0xf;
		ata_link_printk(link, KERN_INFO,
				"SATA link up %s (SStatus %X SControl %X)\n",
@@ -3372,6 +3433,12 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
	unsigned long nodev_deadline = ata_deadline(start, ATA_TMOUT_FF_WAIT);
	int warned = 0;

	/* Slave readiness can't be tested separately from master.  On
	 * M/S emulation configuration, this function should be called
	 * only on the master and it will handle both master and slave.
	 */
	WARN_ON(link == link->ap->slave_link);

	if (time_after(nodev_deadline, deadline))
		nodev_deadline = deadline;

@@ -3593,7 +3660,7 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
	}

	/* no point in trying softreset on offline link */
	if (ata_link_offline(link))
	if (ata_phys_link_offline(link))
		ehc->i.action &= ~ATA_EH_SOFTRESET;

	return 0;
@@ -3671,7 +3738,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
	if (rc)
		goto out;
	/* if link is offline nothing more to do */
	if (ata_link_offline(link))
	if (ata_phys_link_offline(link))
		goto out;

	/* Link is online.  From this point, -ENODEV too is an error. */
@@ -4868,10 +4935,8 @@ int sata_scr_valid(struct ata_link *link)
int sata_scr_read(struct ata_link *link, int reg, u32 *val)
{
	if (ata_is_host_link(link)) {
		struct ata_port *ap = link->ap;

		if (sata_scr_valid(link))
			return ap->ops->scr_read(ap, reg, val);
			return link->ap->ops->scr_read(link, reg, val);
		return -EOPNOTSUPP;
	}

@@ -4897,10 +4962,8 @@ int sata_scr_read(struct ata_link *link, int reg, u32 *val)
int sata_scr_write(struct ata_link *link, int reg, u32 val)
{
	if (ata_is_host_link(link)) {
		struct ata_port *ap = link->ap;

		if (sata_scr_valid(link))
			return ap->ops->scr_write(ap, reg, val);
			return link->ap->ops->scr_write(link, reg, val);
		return -EOPNOTSUPP;
	}

@@ -4925,13 +4988,12 @@ int sata_scr_write(struct ata_link *link, int reg, u32 val)
int sata_scr_write_flush(struct ata_link *link, int reg, u32 val)
{
	if (ata_is_host_link(link)) {
		struct ata_port *ap = link->ap;
		int rc;

		if (sata_scr_valid(link)) {
			rc = ap->ops->scr_write(ap, reg, val);
			rc = link->ap->ops->scr_write(link, reg, val);
			if (rc == 0)
				rc = ap->ops->scr_read(ap, reg, &val);
				rc = link->ap->ops->scr_read(link, reg, &val);
			return rc;
		}
		return -EOPNOTSUPP;
@@ -4941,7 +5003,7 @@ int sata_scr_write_flush(struct ata_link *link, int reg, u32 val)
}

/**
 *	ata_link_online - test whether the given link is online
 *	ata_phys_link_online - test whether the given link is online
 *	@link: ATA link to test
 *
 *	Test whether @link is online.  Note that this function returns
@@ -4952,20 +5014,20 @@ int sata_scr_write_flush(struct ata_link *link, int reg, u32 val)
 *	None.
 *
 *	RETURNS:
 *	1 if the port online status is available and online.
 *	True if the port online status is available and online.
 */
int ata_link_online(struct ata_link *link)
bool ata_phys_link_online(struct ata_link *link)
{
	u32 sstatus;

	if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
	    (sstatus & 0xf) == 0x3)
		return 1;
	return 0;
		return true;
	return false;
}

/**
 *	ata_link_offline - test whether the given link is offline
 *	ata_phys_link_offline - test whether the given link is offline
 *	@link: ATA link to test
 *
 *	Test whether @link is offline.  Note that this function
@@ -4976,16 +5038,68 @@ int ata_link_online(struct ata_link *link)
 *	None.
 *
 *	RETURNS:
 *	1 if the port offline status is available and offline.
 *	True if the port offline status is available and offline.
 */
int ata_link_offline(struct ata_link *link)
bool ata_phys_link_offline(struct ata_link *link)
{
	u32 sstatus;

	if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
	    (sstatus & 0xf) != 0x3)
		return 1;
	return 0;
		return true;
	return false;
}

/**
 *	ata_link_online - test whether the given link is online
 *	@link: ATA link to test
 *
 *	Test whether @link is online.  This is identical to
 *	ata_phys_link_online() when there's no slave link.  When
 *	there's a slave link, this function should only be called on
 *	the master link and will return true if any of M/S links is
 *	online.
 *
 *	LOCKING:
 *	None.
 *
 *	RETURNS:
 *	True if the port online status is available and online.
 */
bool ata_link_online(struct ata_link *link)
{
	struct ata_link *slave = link->ap->slave_link;

	WARN_ON(link == slave);	/* shouldn't be called on slave link */

	return ata_phys_link_online(link) ||
		(slave && ata_phys_link_online(slave));
}

/**
 *	ata_link_offline - test whether the given link is offline
 *	@link: ATA link to test
 *
 *	Test whether @link is offline.  This is identical to
 *	ata_phys_link_offline() when there's no slave link.  When
 *	there's a slave link, this function should only be called on
 *	the master link and will return true if both M/S links are
 *	offline.
 *
 *	LOCKING:
 *	None.
 *
 *	RETURNS:
 *	True if the port offline status is available and offline.
 */
bool ata_link_offline(struct ata_link *link)
{
	struct ata_link *slave = link->ap->slave_link;

	WARN_ON(link == slave);	/* shouldn't be called on slave link */

	return ata_phys_link_offline(link) &&
		(!slave || ata_phys_link_offline(slave));
}

#ifdef CONFIG_PM
@@ -5127,11 +5241,11 @@ int ata_port_start(struct ata_port *ap)
 */
void ata_dev_init(struct ata_device *dev)
{
	struct ata_link *link = dev->link;
	struct ata_link *link = ata_dev_phys_link(dev);
	struct ata_port *ap = link->ap;
	unsigned long flags;

	/* SATA spd limit is bound to the first device */
	/* SATA spd limit is bound to the attached device, reset together */
	link->sata_spd_limit = link->hw_sata_spd_limit;
	link->sata_spd = 0;

@@ -5264,6 +5378,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
	INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
	INIT_LIST_HEAD(&ap->eh_done_q);
	init_waitqueue_head(&ap->eh_wait_q);
	init_completion(&ap->park_req_pending);
	init_timer_deferrable(&ap->fastdrain_timer);
	ap->fastdrain_timer.function = ata_eh_fastdrain_timerfn;
	ap->fastdrain_timer.data = (unsigned long)ap;
@@ -5294,6 +5409,7 @@ static void ata_host_release(struct device *gendev, void *res)
			scsi_host_put(ap->scsi_host);

		kfree(ap->pmp_link);
		kfree(ap->slave_link);
		kfree(ap);
		host->ports[i] = NULL;
	}
@@ -5414,6 +5530,68 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
	return host;
}

/**
 *	ata_slave_link_init - initialize slave link
 *	@ap: port to initialize slave link for
 *
 *	Create and initialize slave link for @ap.  This enables slave
 *	link handling on the port.
 *
 *	In libata, a port contains links and a link contains devices.
 *	There is single host link but if a PMP is attached to it,
 *	there can be multiple fan-out links.  On SATA, there's usually
 *	a single device connected to a link but PATA and SATA
 *	controllers emulating TF based interface can have two - master
 *	and slave.
 *
 *	However, there are a few controllers which don't fit into this
 *	abstraction too well - SATA controllers which emulate TF
 *	interface with both master and slave devices but also have
 *	separate SCR register sets for each device.  These controllers
 *	need separate links for physical link handling
 *	(e.g. onlineness, link speed) but should be treated like a
 *	traditional M/S controller for everything else (e.g. command
 *	issue, softreset).
 *
 *	slave_link is libata's way of handling this class of
 *	controllers without impacting core layer too much.  For
 *	anything other than physical link handling, the default host
 *	link is used for both master and slave.  For physical link
 *	handling, separate @ap->slave_link is used.  All dirty details
 *	are implemented inside libata core layer.  From LLD's POV, the
 *	only difference is that prereset, hardreset and postreset are
 *	called once more for the slave link, so the reset sequence
 *	looks like the following.
 *
 *	prereset(M) -> prereset(S) -> hardreset(M) -> hardreset(S) ->
 *	softreset(M) -> postreset(M) -> postreset(S)
 *
 *	Note that softreset is called only for the master.  Softreset
 *	resets both M/S by definition, so SRST on master should handle
 *	both (the standard method will work just fine).
 *
 *	LOCKING:
 *	Should be called before host is registered.
 *
 *	RETURNS:
 *	0 on success, -errno on failure.
 */
int ata_slave_link_init(struct ata_port *ap)
{
	struct ata_link *link;

	WARN_ON(ap->slave_link);
	WARN_ON(ap->flags & ATA_FLAG_PMP);

	link = kzalloc(sizeof(*link), GFP_KERNEL);
	if (!link)
		return -ENOMEM;

	ata_link_init(ap, link, 1);
	ap->slave_link = link;
	return 0;
}

static void ata_host_stop(struct device *gendev, void *res)
{
	struct ata_host *host = dev_get_drvdata(gendev);
@@ -5640,6 +5818,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)

		/* init sata_spd_limit to the current value */
		sata_link_init_spd(&ap->link);
		if (ap->slave_link)
			sata_link_init_spd(ap->slave_link);

		/* print per-port info to dmesg */
		xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
@@ -6260,10 +6440,12 @@ EXPORT_SYMBOL_GPL(ata_base_port_ops);
EXPORT_SYMBOL_GPL(sata_port_ops);
EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
EXPORT_SYMBOL_GPL(ata_dummy_port_info);
EXPORT_SYMBOL_GPL(__ata_port_next_link);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_host_init);
EXPORT_SYMBOL_GPL(ata_host_alloc);
EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
EXPORT_SYMBOL_GPL(ata_slave_link_init);
EXPORT_SYMBOL_GPL(ata_host_start);
EXPORT_SYMBOL_GPL(ata_host_register);
EXPORT_SYMBOL_GPL(ata_host_activate);
+335 −27

File changed.

Preview size limit exceeded, changes collapsed.

Loading