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

Commit 379e3a82 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (38 commits)
  sata_via: Delay on vt6420 when starting ATAPI DMA write
  ata: Detect Delkin Devices compact flash
  pata_efar: Enable parallel scanning
  pata_atiixp: enable parallel scan
  [libata] pata_atiixp: add locking for parallel scanning
  [libata] pata_efar: add locking for parallel scanning
  libata: Pass host flags into the pci helper
  [libata] pata_marvell: CONFIG_AHCI is really CONFIG_SATA_AHCI
  libata: Allow pata_legacy to be built on non-ISA but PCI systems
  pata_pdc202xx_old: fix UDMA mode for PDC2026x chipsets
  pata_pdc202xx_old: fix UDMA mode for Promise UDMA33 cards
  [libata] pata_at91: fix backslash-continued string
  pata_via: store UDMA masks in via_isa_bridges table
  pata_via: fix address setup timings underlocking
  pata_serverworks: fix error message
  pata_serverworks: fix PIO setup for the second channel
  pata_efar: fix secondary port support
  pata_cypress: fix PIO timings underclocking
  pata_cs5535: use correct values for PIO1 and PIO2 data timings
  pata_cmd64x: remove unused definitions
  ...
parents 8724fdb5 a55ab496
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -446,9 +446,9 @@ config PATA_JMICRON


config PATA_LEGACY
config PATA_LEGACY
	tristate "Legacy ISA PATA support (Experimental)"
	tristate "Legacy ISA PATA support (Experimental)"
	depends on ISA && EXPERIMENTAL
	depends on (ISA || PCI)  && EXPERIMENTAL
	help
	help
	  This option enables support for ISA/VLB bus legacy PATA
	  This option enables support for ISA/VLB/PCI bus legacy PATA
	  ports and allows them to be accessed via the new ATA layer.
	  ports and allows them to be accessed via the new ATA layer.


	  If unsure, say N.
	  If unsure, say N.
+213 −22
Original line number Original line Diff line number Diff line
@@ -93,6 +93,9 @@ enum {
	AHCI_CMD_TBL_AR_SZ	= AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
	AHCI_CMD_TBL_AR_SZ	= AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
	AHCI_PORT_PRIV_DMA_SZ	= AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
	AHCI_PORT_PRIV_DMA_SZ	= AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
				  AHCI_RX_FIS_SZ,
				  AHCI_RX_FIS_SZ,
	AHCI_PORT_PRIV_FBS_DMA_SZ	= AHCI_CMD_SLOT_SZ +
					  AHCI_CMD_TBL_AR_SZ +
					  (AHCI_RX_FIS_SZ * 16),
	AHCI_IRQ_ON_SG		= (1 << 31),
	AHCI_IRQ_ON_SG		= (1 << 31),
	AHCI_CMD_ATAPI		= (1 << 5),
	AHCI_CMD_ATAPI		= (1 << 5),
	AHCI_CMD_WRITE		= (1 << 6),
	AHCI_CMD_WRITE		= (1 << 6),
@@ -170,6 +173,7 @@ enum {
	PORT_SCR_ERR		= 0x30, /* SATA phy register: SError */
	PORT_SCR_ERR		= 0x30, /* SATA phy register: SError */
	PORT_SCR_ACT		= 0x34, /* SATA phy register: SActive */
	PORT_SCR_ACT		= 0x34, /* SATA phy register: SActive */
	PORT_SCR_NTF		= 0x3c, /* SATA phy register: SNotification */
	PORT_SCR_NTF		= 0x3c, /* SATA phy register: SNotification */
	PORT_FBS		= 0x40, /* FIS-based Switching */


	/* PORT_IRQ_{STAT,MASK} bits */
	/* PORT_IRQ_{STAT,MASK} bits */
	PORT_IRQ_COLD_PRES	= (1 << 31), /* cold presence detect */
	PORT_IRQ_COLD_PRES	= (1 << 31), /* cold presence detect */
@@ -208,6 +212,7 @@ enum {
	PORT_CMD_ASP		= (1 << 27), /* Aggressive Slumber/Partial */
	PORT_CMD_ASP		= (1 << 27), /* Aggressive Slumber/Partial */
	PORT_CMD_ALPE		= (1 << 26), /* Aggressive Link PM enable */
	PORT_CMD_ALPE		= (1 << 26), /* Aggressive Link PM enable */
	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
	PORT_CMD_FIS_ON		= (1 << 14), /* FIS DMA engine running */
	PORT_CMD_FIS_ON		= (1 << 14), /* FIS DMA engine running */
@@ -222,6 +227,14 @@ enum {
	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */


	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
	PORT_FBS_DEV_OFFSET	= 8,  /* FBS device to issue offset */
	PORT_FBS_DEV_MASK	= (0xf << PORT_FBS_DEV_OFFSET),  /* FBS.DEV */
	PORT_FBS_SDE		= (1 << 2), /* FBS single device error */
	PORT_FBS_DEC		= (1 << 1), /* FBS device error clear */
	PORT_FBS_EN		= (1 << 0), /* Enable FBS */

	/* hpriv->flags bits */
	/* hpriv->flags bits */
	AHCI_HFLAG_NO_NCQ		= (1 << 0),
	AHCI_HFLAG_NO_NCQ		= (1 << 0),
	AHCI_HFLAG_IGN_IRQ_IF_ERR	= (1 << 1), /* ignore IRQ_IF_ERR */
	AHCI_HFLAG_IGN_IRQ_IF_ERR	= (1 << 1), /* ignore IRQ_IF_ERR */
@@ -304,6 +317,9 @@ struct ahci_port_priv {
	unsigned int		ncq_saw_dmas:1;
	unsigned int		ncq_saw_dmas:1;
	unsigned int		ncq_saw_sdb:1;
	unsigned int		ncq_saw_sdb:1;
	u32 			intr_mask;	/* interrupts to enable */
	u32 			intr_mask;	/* interrupts to enable */
	bool			fbs_supported;	/* set iff FBS is supported */
	bool			fbs_enabled;	/* set iff FBS is enabled */
	int			fbs_last_dev;	/* save FBS.DEV of last FIS */
	/* enclosure management info per PM slot */
	/* enclosure management info per PM slot */
	struct ahci_em_priv	em_priv[EM_MAX_SLOTS];
	struct ahci_em_priv	em_priv[EM_MAX_SLOTS];
};
};
@@ -315,9 +331,12 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
static int ahci_port_start(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static void ahci_freeze(struct ata_port *ap);
static void ahci_freeze(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap);
static void ahci_enable_fbs(struct ata_port *ap);
static void ahci_disable_fbs(struct ata_port *ap);
static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_detach(struct ata_port *ap);
static void ahci_pmp_detach(struct ata_port *ap);
static int ahci_softreset(struct ata_link *link, unsigned int *class,
static int ahci_softreset(struct ata_link *link, unsigned int *class,
@@ -356,10 +375,10 @@ static ssize_t ahci_show_host_version(struct device *dev,
static ssize_t ahci_show_port_cmd(struct device *dev,
static ssize_t ahci_show_port_cmd(struct device *dev,
				  struct device_attribute *attr, char *buf);
				  struct device_attribute *attr, char *buf);


DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);


static struct device_attribute *ahci_shost_attrs[] = {
static struct device_attribute *ahci_shost_attrs[] = {
	&dev_attr_link_power_management_policy,
	&dev_attr_link_power_management_policy,
@@ -390,7 +409,7 @@ static struct scsi_host_template ahci_sht = {
static struct ata_port_operations ahci_ops = {
static struct ata_port_operations ahci_ops = {
	.inherits		= &sata_pmp_port_ops,
	.inherits		= &sata_pmp_port_ops,


	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
	.qc_defer		= ahci_pmp_qc_defer,
	.qc_prep		= ahci_qc_prep,
	.qc_prep		= ahci_qc_prep,
	.qc_issue		= ahci_qc_issue,
	.qc_issue		= ahci_qc_issue,
	.qc_fill_rtf		= ahci_qc_fill_rtf,
	.qc_fill_rtf		= ahci_qc_fill_rtf,
@@ -570,6 +589,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */


	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -2045,6 +2070,17 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
	return si;
	return si;
}
}


static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc)
{
	struct ata_port *ap = qc->ap;
	struct ahci_port_priv *pp = ap->private_data;

	if (!sata_pmp_attached(ap) || pp->fbs_enabled)
		return ata_std_qc_defer(qc);
	else
		return sata_pmp_qc_defer_cmd_switch(qc);
}

static void ahci_qc_prep(struct ata_queued_cmd *qc)
static void ahci_qc_prep(struct ata_queued_cmd *qc)
{
{
	struct ata_port *ap = qc->ap;
	struct ata_port *ap = qc->ap;
@@ -2083,6 +2119,31 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
	ahci_fill_cmd_slot(pp, qc->tag, opts);
	ahci_fill_cmd_slot(pp, qc->tag, opts);
}
}


static void ahci_fbs_dec_intr(struct ata_port *ap)
{
	struct ahci_port_priv *pp = ap->private_data;
	void __iomem *port_mmio = ahci_port_base(ap);
	u32 fbs = readl(port_mmio + PORT_FBS);
	int retries = 3;

	DPRINTK("ENTER\n");
	BUG_ON(!pp->fbs_enabled);

	/* time to wait for DEC is not specified by AHCI spec,
	 * add a retry loop for safety.
	 */
	writel(fbs | PORT_FBS_DEC, port_mmio + PORT_FBS);
	fbs = readl(port_mmio + PORT_FBS);
	while ((fbs & PORT_FBS_DEC) && retries--) {
		udelay(1);
		fbs = readl(port_mmio + PORT_FBS);
	}

	if (fbs & PORT_FBS_DEC)
		dev_printk(KERN_ERR, ap->host->dev,
			   "failed to clear device error\n");
}

static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
{
{
	struct ahci_host_priv *hpriv = ap->host->private_data;
	struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -2091,12 +2152,26 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
	struct ata_link *link = NULL;
	struct ata_link *link = NULL;
	struct ata_queued_cmd *active_qc;
	struct ata_queued_cmd *active_qc;
	struct ata_eh_info *active_ehi;
	struct ata_eh_info *active_ehi;
	bool fbs_need_dec = false;
	u32 serror;
	u32 serror;


	/* determine active link */
	/* determine active link with error */
	if (pp->fbs_enabled) {
		void __iomem *port_mmio = ahci_port_base(ap);
		u32 fbs = readl(port_mmio + PORT_FBS);
		int pmp = fbs >> PORT_FBS_DWE_OFFSET;

		if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links) &&
		    ata_link_online(&ap->pmp_link[pmp])) {
			link = &ap->pmp_link[pmp];
			fbs_need_dec = true;
		}

	} else
		ata_for_each_link(link, ap, EDGE)
		ata_for_each_link(link, ap, EDGE)
			if (ata_link_active(link))
			if (ata_link_active(link))
				break;
				break;

	if (!link)
	if (!link)
		link = &ap->link;
		link = &ap->link;


@@ -2153,8 +2228,13 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
	}
	}


	if (irq_stat & PORT_IRQ_IF_ERR) {
	if (irq_stat & PORT_IRQ_IF_ERR) {
		if (fbs_need_dec)
			active_ehi->err_mask |= AC_ERR_DEV;
		else {
			host_ehi->err_mask |= AC_ERR_ATA_BUS;
			host_ehi->err_mask |= AC_ERR_ATA_BUS;
			host_ehi->action |= ATA_EH_RESET;
			host_ehi->action |= ATA_EH_RESET;
		}

		ata_ehi_push_desc(host_ehi, "interface fatal error");
		ata_ehi_push_desc(host_ehi, "interface fatal error");
	}
	}


@@ -2169,7 +2249,10 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)


	if (irq_stat & PORT_IRQ_FREEZE)
	if (irq_stat & PORT_IRQ_FREEZE)
		ata_port_freeze(ap);
		ata_port_freeze(ap);
	else
	else if (fbs_need_dec) {
		ata_link_abort(link);
		ahci_fbs_dec_intr(ap);
	} else
		ata_port_abort(ap);
		ata_port_abort(ap);
}
}


@@ -2222,14 +2305,21 @@ static void ahci_port_intr(struct ata_port *ap)
			/* If the 'N' bit in word 0 of the FIS is set,
			/* If the 'N' bit in word 0 of the FIS is set,
			 * we just received asynchronous notification.
			 * we just received asynchronous notification.
			 * Tell libata about it.
			 * Tell libata about it.
			 *
			 * Lack of SNotification should not appear in
			 * ahci 1.2, so the workaround is unnecessary
			 * when FBS is enabled.
			 */
			 */
			if (pp->fbs_enabled)
				WARN_ON_ONCE(1);
			else {
				const __le32 *f = pp->rx_fis + RX_FIS_SDB;
				const __le32 *f = pp->rx_fis + RX_FIS_SDB;
				u32 f0 = le32_to_cpu(f[0]);
				u32 f0 = le32_to_cpu(f[0]);

				if (f0 & (1 << 15))
				if (f0 & (1 << 15))
					sata_async_notification(ap);
					sata_async_notification(ap);
			}
			}
		}
		}
	}


	/* pp->active_link is valid iff any command is in flight */
	/* pp->active_link is valid iff any command is in flight */
	if (ap->qc_active && pp->active_link->sactive)
	if (ap->qc_active && pp->active_link->sactive)
@@ -2321,6 +2411,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)


	if (qc->tf.protocol == ATA_PROT_NCQ)
	if (qc->tf.protocol == ATA_PROT_NCQ)
		writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
		writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);

	if (pp->fbs_enabled && pp->fbs_last_dev != qc->dev->link->pmp) {
		u32 fbs = readl(port_mmio + PORT_FBS);
		fbs &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC);
		fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET;
		writel(fbs, port_mmio + PORT_FBS);
		pp->fbs_last_dev = qc->dev->link->pmp;
	}

	writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
	writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);


	ahci_sw_activity(qc->dev->link);
	ahci_sw_activity(qc->dev->link);
@@ -2333,6 +2432,9 @@ static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
	struct ahci_port_priv *pp = qc->ap->private_data;
	struct ahci_port_priv *pp = qc->ap->private_data;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;


	if (pp->fbs_enabled)
		d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;

	ata_tf_from_fis(d2h_fis, &qc->result_tf);
	ata_tf_from_fis(d2h_fis, &qc->result_tf);
	return true;
	return true;
}
}
@@ -2381,6 +2483,71 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
		ahci_kick_engine(ap);
		ahci_kick_engine(ap);
}
}


static void ahci_enable_fbs(struct ata_port *ap)
{
	struct ahci_port_priv *pp = ap->private_data;
	void __iomem *port_mmio = ahci_port_base(ap);
	u32 fbs;
	int rc;

	if (!pp->fbs_supported)
		return;

	fbs = readl(port_mmio + PORT_FBS);
	if (fbs & PORT_FBS_EN) {
		pp->fbs_enabled = true;
		pp->fbs_last_dev = -1; /* initialization */
		return;
	}

	rc = ahci_stop_engine(ap);
	if (rc)
		return;

	writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);
	fbs = readl(port_mmio + PORT_FBS);
	if (fbs & PORT_FBS_EN) {
		dev_printk(KERN_INFO, ap->host->dev, "FBS is enabled.\n");
		pp->fbs_enabled = true;
		pp->fbs_last_dev = -1; /* initialization */
	} else
		dev_printk(KERN_ERR, ap->host->dev, "Failed to enable FBS\n");

	ahci_start_engine(ap);
}

static void ahci_disable_fbs(struct ata_port *ap)
{
	struct ahci_port_priv *pp = ap->private_data;
	void __iomem *port_mmio = ahci_port_base(ap);
	u32 fbs;
	int rc;

	if (!pp->fbs_supported)
		return;

	fbs = readl(port_mmio + PORT_FBS);
	if ((fbs & PORT_FBS_EN) == 0) {
		pp->fbs_enabled = false;
		return;
	}

	rc = ahci_stop_engine(ap);
	if (rc)
		return;

	writel(fbs & ~PORT_FBS_EN, port_mmio + PORT_FBS);
	fbs = readl(port_mmio + PORT_FBS);
	if (fbs & PORT_FBS_EN)
		dev_printk(KERN_ERR, ap->host->dev, "Failed to disable FBS\n");
	else {
		dev_printk(KERN_INFO, ap->host->dev, "FBS is disabled.\n");
		pp->fbs_enabled = false;
	}

	ahci_start_engine(ap);
}

static void ahci_pmp_attach(struct ata_port *ap)
static void ahci_pmp_attach(struct ata_port *ap)
{
{
	void __iomem *port_mmio = ahci_port_base(ap);
	void __iomem *port_mmio = ahci_port_base(ap);
@@ -2391,6 +2558,8 @@ static void ahci_pmp_attach(struct ata_port *ap)
	cmd |= PORT_CMD_PMP;
	cmd |= PORT_CMD_PMP;
	writel(cmd, port_mmio + PORT_CMD);
	writel(cmd, port_mmio + PORT_CMD);


	ahci_enable_fbs(ap);

	pp->intr_mask |= PORT_IRQ_BAD_PMP;
	pp->intr_mask |= PORT_IRQ_BAD_PMP;
	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
}
@@ -2401,6 +2570,8 @@ static void ahci_pmp_detach(struct ata_port *ap)
	struct ahci_port_priv *pp = ap->private_data;
	struct ahci_port_priv *pp = ap->private_data;
	u32 cmd;
	u32 cmd;


	ahci_disable_fbs(ap);

	cmd = readl(port_mmio + PORT_CMD);
	cmd = readl(port_mmio + PORT_CMD);
	cmd &= ~PORT_CMD_PMP;
	cmd &= ~PORT_CMD_PMP;
	writel(cmd, port_mmio + PORT_CMD);
	writel(cmd, port_mmio + PORT_CMD);
@@ -2492,20 +2663,40 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)


static int ahci_port_start(struct ata_port *ap)
static int ahci_port_start(struct ata_port *ap)
{
{
	struct ahci_host_priv *hpriv = ap->host->private_data;
	struct device *dev = ap->host->dev;
	struct device *dev = ap->host->dev;
	struct ahci_port_priv *pp;
	struct ahci_port_priv *pp;
	void *mem;
	void *mem;
	dma_addr_t mem_dma;
	dma_addr_t mem_dma;
	size_t dma_sz, rx_fis_sz;


	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
	if (!pp)
	if (!pp)
		return -ENOMEM;
		return -ENOMEM;


	mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
	/* check FBS capability */
				  GFP_KERNEL);
	if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) {
		void __iomem *port_mmio = ahci_port_base(ap);
		u32 cmd = readl(port_mmio + PORT_CMD);
		if (cmd & PORT_CMD_FBSCP)
			pp->fbs_supported = true;
		else
			dev_printk(KERN_WARNING, dev,
				   "The port is not capable of FBS\n");
	}

	if (pp->fbs_supported) {
		dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ;
		rx_fis_sz = AHCI_RX_FIS_SZ * 16;
	} else {
		dma_sz = AHCI_PORT_PRIV_DMA_SZ;
		rx_fis_sz = AHCI_RX_FIS_SZ;
	}

	mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL);
	if (!mem)
	if (!mem)
		return -ENOMEM;
		return -ENOMEM;
	memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
	memset(mem, 0, dma_sz);


	/*
	/*
	 * First item in chunk of DMA memory: 32-slot command table,
	 * First item in chunk of DMA memory: 32-slot command table,
@@ -2523,8 +2714,8 @@ static int ahci_port_start(struct ata_port *ap)
	pp->rx_fis = mem;
	pp->rx_fis = mem;
	pp->rx_fis_dma = mem_dma;
	pp->rx_fis_dma = mem_dma;


	mem += AHCI_RX_FIS_SZ;
	mem += rx_fis_sz;
	mem_dma += AHCI_RX_FIS_SZ;
	mem_dma += rx_fis_sz;


	/*
	/*
	 * Third item: data area for storing a single command
	 * Third item: data area for storing a single command
+1 −1
Original line number Original line Diff line number Diff line
@@ -155,7 +155,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
			return rc;
			return rc;
		pcim_pin_device(dev);
		pcim_pin_device(dev);
	}
	}
	return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL);
	return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL, 0);
}
}


static struct pci_device_id ata_generic[] = {
static struct pci_device_id ata_generic[] = {
+23 −5
Original line number Original line Diff line number Diff line
@@ -173,6 +173,7 @@ static int piix_sidpr_scr_read(struct ata_link *link,
			       unsigned int reg, u32 *val);
			       unsigned int reg, u32 *val);
static int piix_sidpr_scr_write(struct ata_link *link,
static int piix_sidpr_scr_write(struct ata_link *link,
				unsigned int reg, u32 val);
				unsigned int reg, u32 val);
static bool piix_irq_check(struct ata_port *ap);
#ifdef CONFIG_PM
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int piix_pci_device_resume(struct pci_dev *pdev);
static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -291,6 +292,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
	{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
	{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
	/* SATA Controller IDE (PCH) */
	/* SATA Controller IDE (PCH) */
	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
	/* SATA Controller IDE (CPT) */
	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
	/* SATA Controller IDE (CPT) */
	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
	/* SATA Controller IDE (CPT) */
	{ 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
	/* SATA Controller IDE (CPT) */
	{ 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
	{ }	/* terminate list */
	{ }	/* terminate list */
};
};


@@ -309,8 +318,13 @@ static struct scsi_host_template piix_sht = {
	ATA_BMDMA_SHT(DRV_NAME),
	ATA_BMDMA_SHT(DRV_NAME),
};
};


static struct ata_port_operations piix_pata_ops = {
static struct ata_port_operations piix_sata_ops = {
	.inherits		= &ata_bmdma32_port_ops,
	.inherits		= &ata_bmdma32_port_ops,
	.sff_irq_check		= piix_irq_check,
};

static struct ata_port_operations piix_pata_ops = {
	.inherits		= &piix_sata_ops,
	.cable_detect		= ata_cable_40wire,
	.cable_detect		= ata_cable_40wire,
	.set_piomode		= piix_set_piomode,
	.set_piomode		= piix_set_piomode,
	.set_dmamode		= piix_set_dmamode,
	.set_dmamode		= piix_set_dmamode,
@@ -328,10 +342,6 @@ static struct ata_port_operations ich_pata_ops = {
	.set_dmamode		= ich_set_dmamode,
	.set_dmamode		= ich_set_dmamode,
};
};


static struct ata_port_operations piix_sata_ops = {
	.inherits		= &ata_bmdma32_port_ops,
};

static struct ata_port_operations piix_sidpr_sata_ops = {
static struct ata_port_operations piix_sidpr_sata_ops = {
	.inherits		= &piix_sata_ops,
	.inherits		= &piix_sata_ops,
	.hardreset		= sata_std_hardreset,
	.hardreset		= sata_std_hardreset,
@@ -962,6 +972,14 @@ static int piix_sidpr_scr_write(struct ata_link *link,
	return 0;
	return 0;
}
}


static bool piix_irq_check(struct ata_port *ap)
{
	if (unlikely(!ap->ioaddr.bmdma_addr))
		return false;

	return ap->ops->bmdma_status(ap) & ATA_DMA_INTR;
}

#ifdef CONFIG_PM
#ifdef CONFIG_PM
static int piix_broken_suspend(void)
static int piix_broken_suspend(void)
{
{
+11 −6
Original line number Original line Diff line number Diff line
@@ -3211,6 +3211,7 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
int ata_timing_compute(struct ata_device *adev, unsigned short speed,
int ata_timing_compute(struct ata_device *adev, unsigned short speed,
		       struct ata_timing *t, int T, int UT)
		       struct ata_timing *t, int T, int UT)
{
{
	const u16 *id = adev->id;
	const struct ata_timing *s;
	const struct ata_timing *s;
	struct ata_timing p;
	struct ata_timing p;


@@ -3228,14 +3229,18 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
	 * PIO/MW_DMA cycle timing.
	 * PIO/MW_DMA cycle timing.
	 */
	 */


	if (adev->id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE drive */
	if (id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE drive */
		memset(&p, 0, sizeof(p));
		memset(&p, 0, sizeof(p));

		if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
		if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
			if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
			if (speed <= XFER_PIO_2)
					    else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
				p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
		} else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
			else if ((speed <= XFER_PIO_4) ||
			p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
				 (speed == XFER_PIO_5 && !ata_id_is_cfa(id)))
		}
				p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
		} else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
			p.cycle = id[ATA_ID_EIDE_DMA_MIN];

		ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
		ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
	}
	}


Loading