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

Commit 6adc74b7 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:
  [libata] ata_piix: Enable parallel scan
  sata_nv: use hardreset only for post-boot probing
  [libata] ahci: Restore SB600 SATA controller 64 bit DMA
  ata_piix: Remove stale comment
  ata_piix: Turn on hotplugging support for older chips
  ahci: misc cleanups for EM stuff
  [libata] get rid of ATA_MAX_QUEUE loop in ata_qc_complete_multiple() v2
  sata_sil: enable 32-bit PIO
  sata_sx4: speed up ECC initialization
  libata-sff: avoid byte swapping in ata_sff_data_xfer()
  [libata] ahci: use less error-prone array initializers
parents c9059598 517d3cc1
Loading
Loading
Loading
Loading
+68 −19
Original line number Diff line number Diff line
@@ -77,8 +77,6 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
			      size_t size);
static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
					ssize_t size);
#define MAX_SLOTS 8
#define MAX_RETRY 15

enum {
	AHCI_PCI_BAR		= 5,
@@ -231,6 +229,10 @@ enum {

	ICH_MAP				= 0x90, /* ICH MAP register */

	/* em constants */
	EM_MAX_SLOTS			= 8,
	EM_MAX_RETRY			= 5,

	/* em_ctl bits */
	EM_CTL_RST			= (1 << 9), /* Reset */
	EM_CTL_TM			= (1 << 8), /* Transmit Message */
@@ -282,8 +284,8 @@ struct ahci_port_priv {
	unsigned int		ncq_saw_dmas:1;
	unsigned int		ncq_saw_sdb:1;
	u32 			intr_mask;	/* interrupts to enable */
	struct ahci_em_priv	em_priv[MAX_SLOTS];/* enclosure management info
					 	 * per PM slot */
	/* enclosure management info per PM slot */
	struct ahci_em_priv	em_priv[EM_MAX_SLOTS];
};

static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
@@ -313,7 +315,6 @@ static void ahci_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
static int ahci_port_resume(struct ata_port *ap);
static void ahci_dev_config(struct ata_device *dev);
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
			       u32 opts);
#ifdef CONFIG_PM
@@ -404,14 +405,14 @@ static struct ata_port_operations ahci_sb600_ops = {
#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)

static const struct ata_port_info ahci_port_info[] = {
	/* board_ahci */
	[board_ahci] =
	{
		.flags		= AHCI_FLAG_COMMON,
		.pio_mask	= ATA_PIO4,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
	},
	/* board_ahci_vt8251 */
	[board_ahci_vt8251] =
	{
		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
		.flags		= AHCI_FLAG_COMMON,
@@ -419,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = {
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_vt8251_ops,
	},
	/* board_ahci_ign_iferr */
	[board_ahci_ign_iferr] =
	{
		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
		.flags		= AHCI_FLAG_COMMON,
@@ -427,17 +428,16 @@ static const struct ata_port_info ahci_port_info[] = {
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
	},
	/* board_ahci_sb600 */
	[board_ahci_sb600] =
	{
		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
				 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
				 AHCI_HFLAG_SECT255),
				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255),
		.flags		= AHCI_FLAG_COMMON,
		.pio_mask	= ATA_PIO4,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_sb600_ops,
	},
	/* board_ahci_mv */
	[board_ahci_mv] =
	{
		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
@@ -447,7 +447,7 @@ static const struct ata_port_info ahci_port_info[] = {
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
	},
	/* board_ahci_sb700, for SB700 and SB800 */
	[board_ahci_sb700] =	/* for SB700 and SB800 */
	{
		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
		.flags		= AHCI_FLAG_COMMON,
@@ -455,7 +455,7 @@ static const struct ata_port_info ahci_port_info[] = {
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_sb600_ops,
	},
	/* board_ahci_mcp65 */
	[board_ahci_mcp65] =
	{
		AHCI_HFLAGS	(AHCI_HFLAG_YES_NCQ),
		.flags		= AHCI_FLAG_COMMON,
@@ -463,7 +463,7 @@ static const struct ata_port_info ahci_port_info[] = {
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
	},
	/* board_ahci_nopmp */
	[board_ahci_nopmp] =
	{
		AHCI_HFLAGS	(AHCI_HFLAG_NO_PMP),
		.flags		= AHCI_FLAG_COMMON,
@@ -1141,12 +1141,12 @@ static void ahci_start_port(struct ata_port *ap)
			emp = &pp->em_priv[link->pmp];

			/* EM Transmit bit maybe busy during init */
			for (i = 0; i < MAX_RETRY; i++) {
			for (i = 0; i < EM_MAX_RETRY; i++) {
				rc = ahci_transmit_led_message(ap,
							       emp->led_state,
							       4);
				if (rc == -EBUSY)
					udelay(100);
					msleep(1);
				else
					break;
			}
@@ -1340,7 +1340,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,

	/* get the slot number from the message */
	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
	if (pmp < MAX_SLOTS)
	if (pmp < EM_MAX_SLOTS)
		emp = &pp->em_priv[pmp];
	else
		return -EINVAL;
@@ -1408,7 +1408,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,

	/* get the slot number from the message */
	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
	if (pmp < MAX_SLOTS)
	if (pmp < EM_MAX_SLOTS)
		emp = &pp->em_priv[pmp];
	else
		return -EINVAL;
@@ -2584,6 +2584,51 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
	}
}

/*
 * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older
 * BIOS.  The oldest version known to be broken is 0901 and working is
 * 1501 which was released on 2007-10-26.  Force 32bit DMA on anything
 * older than 1501.  Please read bko#9412 for more info.
 */
static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev)
{
	static const struct dmi_system_id sysids[] = {
		{
			.ident = "ASUS M2A-VM",
			.matches = {
				DMI_MATCH(DMI_BOARD_VENDOR,
					  "ASUSTeK Computer INC."),
				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
			},
		},
		{ }
	};
	const char *cutoff_mmdd = "10/26";
	const char *date;
	int year;

	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
	    !dmi_check_system(sysids))
		return false;

	/*
	 * Argh.... both version and date are free form strings.
	 * Let's hope they're using the same date format across
	 * different versions.
	 */
	date = dmi_get_system_info(DMI_BIOS_DATE);
	year = dmi_get_year(DMI_BIOS_DATE);
	if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' &&
	    (year > 2007 ||
	     (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0)))
		return false;

	dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, "
		   "forcing 32bit DMA, update BIOS\n");

	return true;
}

static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
{
	static const struct dmi_system_id broken_systems[] = {
@@ -2744,6 +2789,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;

	/* apply ASUS M2A_VM quirk */
	if (ahci_asus_m2a_vm_32bit_only(pdev))
		hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;

	if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
		pci_enable_msi(pdev);

+5 −6
Original line number Diff line number Diff line
@@ -223,9 +223,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
	/* ICH8 Mobile PATA Controller */
	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },

	/* NOTE: The following PCI ids must be kept in sync with the
	 * list in drivers/pci/quirks.c.
	 */
	/* SATA ports */
	
	/* 82801EB (ICH5) */
	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
@@ -1509,8 +1507,8 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
		dev_printk(KERN_DEBUG, &pdev->dev,
			   "version " DRV_VERSION "\n");

	/* no hotplugging support (FIXME) */
	if (!in_module_init)
	/* no hotplugging support for later devices (FIXME) */
	if (!in_module_init && ent->driver_data >= ich5_sata)
		return -ENODEV;

	if (piix_broken_system_poweroff(pdev)) {
@@ -1591,6 +1589,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
		host->ports[1]->mwdma_mask = 0;
		host->ports[1]->udma_mask = 0;
	}
	host->flags |= ATA_HOST_PARALLEL_SCAN;

	pci_set_master(pdev);
	return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
+5 −6
Original line number Diff line number Diff line
@@ -5031,7 +5031,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)
{
	int nr_done = 0;
	u32 done_mask;
	int i;

	done_mask = ap->qc_active ^ qc_active;

@@ -5041,16 +5040,16 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)
		return -EINVAL;
	}

	for (i = 0; i < ATA_MAX_QUEUE; i++) {
	while (done_mask) {
		struct ata_queued_cmd *qc;
		unsigned int tag = __ffs(done_mask);

		if (!(done_mask & (1 << i)))
			continue;

		if ((qc = ata_qc_from_tag(ap, i))) {
		qc = ata_qc_from_tag(ap, tag);
		if (qc) {
			ata_qc_complete(qc);
			nr_done++;
		}
		done_mask &= ~(1 << tag);
	}

	return nr_done;
+13 −7
Original line number Diff line number Diff line
@@ -727,17 +727,23 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
	else
		iowrite16_rep(data_addr, buf, words);

	/* Transfer trailing 1 byte, if any. */
	/* Transfer trailing byte, if any. */
	if (unlikely(buflen & 0x01)) {
		__le16 align_buf[1] = { 0 };
		unsigned char *trailing_buf = buf + buflen - 1;
		unsigned char pad[2];

		/* Point buf to the tail of buffer */
		buf += buflen - 1;

		/*
		 * Use io*16_rep() accessors here as well to avoid pointlessly
		 * swapping bytes to and fro on the big endian machines...
		 */
		if (rw == READ) {
			align_buf[0] = cpu_to_le16(ioread16(data_addr));
			memcpy(trailing_buf, align_buf, 1);
			ioread16_rep(data_addr, pad, 1);
			*buf = pad[0];
		} else {
			memcpy(align_buf, trailing_buf, 1);
			iowrite16(le16_to_cpu(align_buf[0]), data_addr);
			pad[0] = *buf;
			iowrite16_rep(data_addr, pad, 1);
		}
		words++;
	}
+81 −50
Original line number Diff line number Diff line
@@ -305,7 +305,7 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);

static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
static int nv_hardreset(struct ata_link *link, unsigned int *class,
			unsigned long deadline);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
@@ -406,49 +406,82 @@ static struct scsi_host_template nv_swncq_sht = {
	.slave_configure	= nv_swncq_slave_config,
};

static struct ata_port_operations nv_common_ops = {
/*
 * NV SATA controllers have various different problems with hardreset
 * protocol depending on the specific controller and device.
 *
 * GENERIC:
 *
 *  bko11195 reports that link doesn't come online after hardreset on
 *  generic nv's and there have been several other similar reports on
 *  linux-ide.
 *
 *  bko12351#c23 reports that warmplug on MCP61 doesn't work with
 *  softreset.
 *
 * NF2/3:
 *
 *  bko3352 reports nf2/3 controllers can't determine device signature
 *  reliably after hardreset.  The following thread reports detection
 *  failure on cold boot with the standard debouncing timing.
 *
 *  http://thread.gmane.org/gmane.linux.ide/34098
 *
 *  bko12176 reports that hardreset fails to bring up the link during
 *  boot on nf2.
 *
 * CK804:
 *
 *  For initial probing after boot and hot plugging, hardreset mostly
 *  works fine on CK804 but curiously, reprobing on the initial port
 *  by rescanning or rmmod/insmod fails to acquire the initial D2H Reg
 *  FIS in somewhat undeterministic way.
 *
 * SWNCQ:
 *
 *  bko12351 reports that when SWNCQ is enabled, for hotplug to work,
 *  hardreset should be used and hardreset can't report proper
 *  signature, which suggests that mcp5x is closer to nf2 as long as
 *  reset quirkiness is concerned.
 *
 *  bko12703 reports that boot probing fails for intel SSD with
 *  hardreset.  Link fails to come online.  Softreset works fine.
 *
 * The failures are varied but the following patterns seem true for
 * all flavors.
 *
 * - Softreset during boot always works.
 *
 * - Hardreset during boot sometimes fails to bring up the link on
 *   certain comibnations and device signature acquisition is
 *   unreliable.
 *
 * - Hardreset is often necessary after hotplug.
 *
 * So, preferring softreset for boot probing and error handling (as
 * hardreset might bring down the link) but using hardreset for
 * post-boot probing should work around the above issues in most
 * cases.  Define nv_hardreset() which only kicks in for post-boot
 * probing and use it for all variants.
 */
static struct ata_port_operations nv_generic_ops = {
	.inherits		= &ata_bmdma_port_ops,
	.lost_interrupt		= ATA_OP_NULL,
	.scr_read		= nv_scr_read,
	.scr_write		= nv_scr_write,
	.hardreset		= nv_hardreset,
};

/* OSDL bz11195 reports that link doesn't come online after hardreset
 * on generic nv's and there have been several other similar reports
 * on linux-ide.  Disable hardreset for generic nv's.
 */
static struct ata_port_operations nv_generic_ops = {
	.inherits		= &nv_common_ops,
	.hardreset		= ATA_OP_NULL,
};

/* nf2 is ripe with hardreset related problems.
 *
 * kernel bz#3352 reports nf2/3 controllers can't determine device
 * signature reliably.  The following thread reports detection failure
 * on cold boot with the standard debouncing timing.
 *
 * http://thread.gmane.org/gmane.linux.ide/34098
 *
 * And bz#12176 reports that hardreset simply doesn't work on nf2.
 * Give up on it and just don't do hardreset.
 */
static struct ata_port_operations nv_nf2_ops = {
	.inherits		= &nv_generic_ops,
	.freeze			= nv_nf2_freeze,
	.thaw			= nv_nf2_thaw,
};

/* For initial probing after boot and hot plugging, hardreset mostly
 * works fine on CK804 but curiously, reprobing on the initial port by
 * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
 * in somewhat undeterministic way.  Use noclassify hardreset.
 */
static struct ata_port_operations nv_ck804_ops = {
	.inherits		= &nv_common_ops,
	.inherits		= &nv_generic_ops,
	.freeze			= nv_ck804_freeze,
	.thaw			= nv_ck804_thaw,
	.hardreset		= nv_noclassify_hardreset,
	.host_stop		= nv_ck804_host_stop,
};

@@ -476,19 +509,8 @@ static struct ata_port_operations nv_adma_ops = {
	.host_stop		= nv_adma_host_stop,
};

/* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to
 * work, hardreset should be used and hardreset can't report proper
 * signature, which suggests that mcp5x is closer to nf2 as long as
 * reset quirkiness is concerned.  Define separate ops for mcp5x with
 * nv_noclassify_hardreset().
 */
static struct ata_port_operations nv_mcp5x_ops = {
	.inherits		= &nv_common_ops,
	.hardreset		= nv_noclassify_hardreset,
};

static struct ata_port_operations nv_swncq_ops = {
	.inherits		= &nv_mcp5x_ops,
	.inherits		= &nv_generic_ops,

	.qc_defer		= ata_std_qc_defer,
	.qc_prep		= nv_swncq_qc_prep,
@@ -557,7 +579,7 @@ static const struct ata_port_info nv_port_info[] = {
		.pio_mask	= NV_PIO_MASK,
		.mwdma_mask	= NV_MWDMA_MASK,
		.udma_mask	= NV_UDMA_MASK,
		.port_ops	= &nv_mcp5x_ops,
		.port_ops	= &nv_generic_ops,
		.private_data	= NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
	},
	/* SWNCQ */
@@ -1559,15 +1581,24 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
	return 0;
}

static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
static int nv_hardreset(struct ata_link *link, unsigned int *class,
			unsigned long deadline)
{
	bool online;
	int rc;
	struct ata_eh_context *ehc = &link->eh_context;

	rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
				 &online, NULL);
	return online ? -EAGAIN : rc;
	/* Do hardreset iff it's post-boot probing, please read the
	 * comment above port ops for details.
	 */
	if (!(link->ap->pflags & ATA_PFLAG_LOADING) &&
	    !ata_dev_enabled(link->device))
		sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
				    NULL, NULL);
	else if (!(ehc->i.flags & ATA_EHI_QUIET))
		ata_link_printk(link, KERN_INFO,
				"nv: skipping hardreset on occupied port\n");

	/* device signature acquisition is unreliable */
	return -EAGAIN;
}

static void nv_nf2_freeze(struct ata_port *ap)
Loading