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

Commit 57399ec9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (21 commits)
  libata: remove irq_on from ata_bus_reset() and ata_std_postreset()
  ata_piix: kill incorrect invalid map value warning
  libata: add another Maxtor drive with broken NCQ to the list
  [libata] sata_mv: Fix and clean up per-chip-generation tests
  [libata] sata_mv: Convert to new exception handling (EH) infrastructure
  [libata] sata_mv: minor bug fixes, enhancements, and cleanups (prep for new EH)
  [libata] sata_mv: Minor cleanups and renaming, preparing for new EH & NCQ
  libata-link: add PMP related ATA constants
  libata-link: separate out ata_eh_handle_dev_fail()
  pata_hpt3x3: fix DMA Kconfig option to actually have a hope of working
  Add Hitachi HDS7250SASUN500G 0621KTAWSD to NCQ blacklist
  pata_scc.c: Workaround for errata A308
  libata: add FUJITSU MHV2080BH to NCQ blacklist
  pata_hpt3x3: major reworking and testing
  libata: clean up horkage handling
  libata: quirk IOMEGA ZIP 250 ATAPI FLOPPY
  libata: simplify PCI legacy SFF host handling
  pata_mpc52xx: suspend/resume support
  sata_promise: SATA hotplug support, take 2
  pata_sis: FIFO whack
  ...
parents e1bd2ac5 c6e54a57
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -309,7 +309,7 @@ config PATA_HPT3X2N
	  If unsure, say N.

config PATA_HPT3X3
	tristate "HPT 343/363 PATA support (Experimental)"
	tristate "HPT 343/363 PATA support"
	depends on PCI
	help
	  This option enables support for the HPT 343/363
@@ -317,6 +317,14 @@ config PATA_HPT3X3

	  If unsure, say N.

config PATA_HPT3X3_DMA
	bool "HPT 343/363 DMA support (Experimental)"
	depends on PATA_HPT3X3
	help
	  This option enables DMA support for the HPT343/363
	  controllers. Enable with care as there are still some
	  problems with DMA on this chipset.

config PATA_ISAPNP
	tristate "ISA Plug and Play PATA support (Experimental)"
	depends on EXPERIMENTAL && ISAPNP
+1 −1
Original line number Diff line number Diff line
@@ -414,7 +414,7 @@ static const struct piix_map_db ich6m_map_db = {
	 */
	.map = {
		/* PM   PS   SM   SS       MAP */
		{  P0,  P2,  RV,  RV }, /* 00b */
		{  P0,  P2,  NA,  NA }, /* 00b */
		{ IDE, IDE,  P1,  P3 }, /* 01b */
		{  P0,  P2, IDE, IDE }, /* 10b */
		{  RV,  RV,  RV,  RV },
+20 −54
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
					u16 heads, u16 sectors);
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
static void ata_dev_xfermask(struct ata_device *dev);
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);

unsigned int ata_print_id = 1;
static struct workqueue_struct *ata_wq;
@@ -1283,18 +1284,11 @@ static unsigned int ata_id_xfermask(const u16 *id)
void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
			 unsigned long delay)
{
	int rc;

	if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
		return;

	PREPARE_DELAYED_WORK(&ap->port_task, fn);
	ap->port_task_data = data;

	rc = queue_delayed_work(ata_wq, &ap->port_task, delay);

	/* rc == 0 means that another user is using port task */
	WARN_ON(rc == 0);
	/* may fail if ata_port_flush_task() in progress */
	queue_delayed_work(ata_wq, &ap->port_task, delay);
}

/**
@@ -1309,32 +1303,9 @@ void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
 */
void ata_port_flush_task(struct ata_port *ap)
{
	unsigned long flags;

	DPRINTK("ENTER\n");

	spin_lock_irqsave(ap->lock, flags);
	ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
	spin_unlock_irqrestore(ap->lock, flags);

	DPRINTK("flush #1\n");
	cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */

	/*
	 * At this point, if a task is running, it's guaranteed to see
	 * the FLUSH flag; thus, it will never queue pio tasks again.
	 * Cancel and flush.
	 */
	if (!cancel_delayed_work(&ap->port_task)) {
		if (ata_msg_ctl(ap))
			ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
					__FUNCTION__);
		cancel_work_sync(&ap->port_task.work);
	}

	spin_lock_irqsave(ap->lock, flags);
	ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
	spin_unlock_irqrestore(ap->lock, flags);
	cancel_rearming_delayed_work(&ap->port_task);

	if (ata_msg_ctl(ap))
		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
@@ -1814,7 +1785,7 @@ static void ata_dev_config_ncq(struct ata_device *dev,
		desc[0] = '\0';
		return;
	}
	if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
	if (dev->horkage & ATA_HORKAGE_NONCQ) {
		snprintf(desc, desc_sz, "NCQ (not used)");
		return;
	}
@@ -1863,6 +1834,9 @@ int ata_dev_configure(struct ata_device *dev)
	if (ata_msg_probe(ap))
		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);

	/* set horkage */
	dev->horkage |= ata_dev_blacklisted(dev);

	/* let ACPI work its magic */
	rc = ata_acpi_on_devcfg(dev);
	if (rc)
@@ -2038,7 +2012,7 @@ int ata_dev_configure(struct ata_device *dev)
		dev->max_sectors = ATA_MAX_SECTORS;
	}

	if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128)
	if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
		dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
					 dev->max_sectors);

@@ -3190,9 +3164,6 @@ void ata_bus_reset(struct ata_port *ap)
	if ((slave_possible) && (err != 0x81))
		ap->device[1].class = ata_dev_try_classify(ap, 1, &err);

	/* re-enable interrupts */
	ap->ops->irq_on(ap);

	/* is double-select really necessary? */
	if (ap->device[1].class != ATA_DEV_NONE)
		ap->ops->dev_select(ap, 1);
@@ -3577,10 +3548,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
	if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
		sata_scr_write(ap, SCR_ERROR, serror);

	/* re-enable interrupts */
	if (!ap->ops->error_handler)
		ap->ops->irq_on(ap);

	/* is double-select really necessary? */
	if (classes[0] != ATA_DEV_NONE)
		ap->ops->dev_select(ap, 1);
@@ -3770,6 +3737,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ "SAMSUNG CD-ROM SN-124","N001",	ATA_HORKAGE_NODMA },
	{ "Seagate STT20000A", NULL,		ATA_HORKAGE_NODMA },
	{ "IOMEGA  ZIP 250       ATAPI", NULL,	ATA_HORKAGE_NODMA }, /* temporary fix */
	{ "IOMEGA  ZIP 250       ATAPI       Floppy",
				NULL,		ATA_HORKAGE_NODMA },

	/* Weird ATAPI devices */
	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
@@ -3783,7 +3752,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ "FUJITSU MHT2060BH",	NULL,		ATA_HORKAGE_NONCQ },
	/* NCQ is broken */
	{ "Maxtor 6L250S0",     "BANC1G10",     ATA_HORKAGE_NONCQ },
	{ "Maxtor 6B200M0",	"BANC1BM0",	ATA_HORKAGE_NONCQ },
	{ "Maxtor 6B200M0",	"BANC1B10",	ATA_HORKAGE_NONCQ },
	{ "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI",
	 ATA_HORKAGE_NONCQ },
	/* NCQ hard hangs device under heavier load, needs hard power cycle */
	{ "Maxtor 6B250S0",	"BANC1B70",	ATA_HORKAGE_NONCQ },
	/* Blacklist entries taken from Silicon Image 3124/3132
@@ -3796,6 +3768,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ "HTS541612J9SA00",	"SBDIC7JP",	ATA_HORKAGE_NONCQ, },
	{ "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
	{ "WDC WD740ADFD-00NLR1", NULL,		ATA_HORKAGE_NONCQ, },
	{ "FUJITSU MHV2080BH",	"00840028",	ATA_HORKAGE_NONCQ, },

	/* Devices with NCQ limits */

@@ -3803,7 +3776,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ }
};

unsigned long ata_device_blacklisted(const struct ata_device *dev)
static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
{
	unsigned char model_num[ATA_ID_PROD_LEN + 1];
	unsigned char model_rev[ATA_ID_FW_REV_LEN + 1];
@@ -3833,7 +3806,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
	if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
	    (dev->flags & ATA_DFLAG_CDB_INTR))
		return 1;
	return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
	return (dev->horkage & ATA_HORKAGE_NODMA) ? 1 : 0;
}

/**
@@ -6557,13 +6530,7 @@ void ata_port_detach(struct ata_port *ap)
	spin_unlock_irqrestore(ap->lock, flags);

	ata_port_wait_eh(ap);

	/* Flush hotplug task.  The sequence is similar to
	 * ata_port_flush_task().
	 */
	cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */
	cancel_delayed_work(&ap->hotplug_task);
	cancel_work_sync(&ap->hotplug_task.work);
	cancel_rearming_delayed_work(&ap->hotplug_task);

 skip_eh:
	/* remove the associated SCSI host */
@@ -6952,7 +6919,6 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
EXPORT_SYMBOL_GPL(ata_device_blacklisted);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);

EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
@@ -6961,9 +6927,9 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);

#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host);
EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
#ifdef CONFIG_PM
+52 −44
Original line number Diff line number Diff line
@@ -1897,6 +1897,57 @@ static int ata_eh_skip_recovery(struct ata_port *ap)
	return 1;
}

static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
{
	struct ata_port *ap = dev->ap;
	struct ata_eh_context *ehc = &ap->eh_context;

	ehc->tries[dev->devno]--;

	switch (err) {
	case -ENODEV:
		/* device missing or wrong IDENTIFY data, schedule probing */
		ehc->i.probe_mask |= (1 << dev->devno);
	case -EINVAL:
		/* give it just one more chance */
		ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
	case -EIO:
		if (ehc->tries[dev->devno] == 1) {
			/* This is the last chance, better to slow
			 * down than lose it.
			 */
			sata_down_spd_limit(ap);
			ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
		}
	}

	if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
		/* disable device if it has used up all its chances */
		ata_dev_disable(dev);

		/* detach if offline */
		if (ata_port_offline(ap))
			ata_eh_detach_dev(dev);

		/* probe if requested */
		if ((ehc->i.probe_mask & (1 << dev->devno)) &&
		    !(ehc->did_probe_mask & (1 << dev->devno))) {
			ata_eh_detach_dev(dev);
			ata_dev_init(dev);

			ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
			ehc->did_probe_mask |= (1 << dev->devno);
			ehc->i.action |= ATA_EH_SOFTRESET;
		}
	} else {
		/* soft didn't work?  be haaaaard */
		if (ehc->i.flags & ATA_EHI_DID_RESET)
			ehc->i.action |= ATA_EH_HARDRESET;
		else
			ehc->i.action |= ATA_EH_SOFTRESET;
	}
}

/**
 *	ata_eh_recover - recover host port after error
 *	@ap: host port to recover
@@ -1997,50 +2048,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
	goto out;

 dev_fail:
	ehc->tries[dev->devno]--;

	switch (rc) {
	case -ENODEV:
		/* device missing or wrong IDENTIFY data, schedule probing */
		ehc->i.probe_mask |= (1 << dev->devno);
	case -EINVAL:
		/* give it just one more chance */
		ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
	case -EIO:
		if (ehc->tries[dev->devno] == 1) {
			/* This is the last chance, better to slow
			 * down than lose it.
			 */
			sata_down_spd_limit(ap);
			ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
		}
	}

	if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
		/* disable device if it has used up all its chances */
		ata_dev_disable(dev);

		/* detach if offline */
		if (ata_port_offline(ap))
			ata_eh_detach_dev(dev);

		/* probe if requested */
		if ((ehc->i.probe_mask & (1 << dev->devno)) &&
		    !(ehc->did_probe_mask & (1 << dev->devno))) {
			ata_eh_detach_dev(dev);
			ata_dev_init(dev);

			ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
			ehc->did_probe_mask |= (1 << dev->devno);
			ehc->i.action |= ATA_EH_SOFTRESET;
		}
	} else {
		/* soft didn't work?  be haaaaard */
		if (ehc->i.flags & ATA_EHI_DID_RESET)
			ehc->i.action |= ATA_EH_HARDRESET;
		else
			ehc->i.action |= ATA_EH_SOFTRESET;
	}
	ata_eh_handle_dev_fail(dev, rc);

	if (ata_port_nr_enabled(ap)) {
		ata_port_printk(ap, KERN_WARNING, "failed to recover some "
+32 −256
Original line number Diff line number Diff line
@@ -604,13 +604,17 @@ int ata_pci_init_bmdma(struct ata_host *host)
}

/**
 *	ata_pci_init_native_host - acquire native ATA resources and init host
 *	ata_pci_init_sff_host - acquire native PCI ATA resources and init host
 *	@host: target ATA host
 *
 *	Acquire native PCI ATA resources for @host and initialize the
 *	first two ports of @host accordingly.  Ports marked dummy are
 *	skipped and allocation failure makes the port dummy.
 *
 *	Note that native PCI resources are valid even for legacy hosts
 *	as we fix up pdev resources array early in boot, so this
 *	function can be used for both native and legacy SFF hosts.
 *
 *	LOCKING:
 *	Inherited from calling layer (may sleep).
 *
@@ -618,7 +622,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
 *	0 if at least one port is initialized, -ENODEV if no port is
 *	available.
 */
int ata_pci_init_native_host(struct ata_host *host)
int ata_pci_init_sff_host(struct ata_host *host)
{
	struct device *gdev = host->dev;
	struct pci_dev *pdev = to_pci_dev(gdev);
@@ -673,7 +677,7 @@ int ata_pci_init_native_host(struct ata_host *host)
}

/**
 *	ata_pci_prepare_native_host - helper to prepare native PCI ATA host
 *	ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
 *	@pdev: target PCI device
 *	@ppi: array of port_info, must be enough for two ports
 *	@r_host: out argument for the initialized ATA host
@@ -687,7 +691,7 @@ int ata_pci_init_native_host(struct ata_host *host)
 *	RETURNS:
 *	0 on success, -errno otherwise.
 */
int ata_pci_prepare_native_host(struct pci_dev *pdev,
int ata_pci_prepare_sff_host(struct pci_dev *pdev,
			     const struct ata_port_info * const * ppi,
			     struct ata_host **r_host)
{
@@ -705,7 +709,7 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
		goto err_out;
	}

	rc = ata_pci_init_native_host(host);
	rc = ata_pci_init_sff_host(host);
	if (rc)
		goto err_out;

@@ -730,221 +734,6 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
	return rc;
}

struct ata_legacy_devres {
	unsigned int	mask;
	unsigned long	cmd_port[2];
	void __iomem *	cmd_addr[2];
	void __iomem *	ctl_addr[2];
	unsigned int	irq[2];
	void *		irq_dev_id[2];
};

static void ata_legacy_free_irqs(struct ata_legacy_devres *legacy_dr)
{
	int i;

	for (i = 0; i < 2; i++) {
		if (!legacy_dr->irq[i])
			continue;

		free_irq(legacy_dr->irq[i], legacy_dr->irq_dev_id[i]);
		legacy_dr->irq[i] = 0;
		legacy_dr->irq_dev_id[i] = NULL;
	}
}

static void ata_legacy_release(struct device *gdev, void *res)
{
	struct ata_legacy_devres *this = res;
	int i;

	ata_legacy_free_irqs(this);

	for (i = 0; i < 2; i++) {
		if (this->cmd_addr[i])
			ioport_unmap(this->cmd_addr[i]);
		if (this->ctl_addr[i])
			ioport_unmap(this->ctl_addr[i]);
		if (this->cmd_port[i])
			release_region(this->cmd_port[i], 8);
	}
}

static int ata_init_legacy_port(struct ata_port *ap,
				struct ata_legacy_devres *legacy_dr)
{
	struct ata_host *host = ap->host;
	int port_no = ap->port_no;
	unsigned long cmd_port, ctl_port;

	if (port_no == 0) {
		cmd_port = ATA_PRIMARY_CMD;
		ctl_port = ATA_PRIMARY_CTL;
	} else {
		cmd_port = ATA_SECONDARY_CMD;
		ctl_port = ATA_SECONDARY_CTL;
	}

	/* request cmd_port */
	if (request_region(cmd_port, 8, "libata"))
		legacy_dr->cmd_port[port_no] = cmd_port;
	else {
		dev_printk(KERN_WARNING, host->dev,
			   "0x%0lX IDE port busy\n", cmd_port);
		return -EBUSY;
	}

	/* iomap cmd and ctl ports */
	legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8);
	legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1);
	if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) {
		dev_printk(KERN_WARNING, host->dev,
			   "failed to map cmd/ctl ports\n");
		return -ENOMEM;
	}

	/* init IO addresses */
	ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no];
	ap->ioaddr.altstatus_addr = legacy_dr->ctl_addr[port_no];
	ap->ioaddr.ctl_addr = legacy_dr->ctl_addr[port_no];
	ata_std_ports(&ap->ioaddr);

	return 0;
}

/**
 *	ata_init_legacy_host - acquire legacy ATA resources and init ATA host
 *	@host: target ATA host
 *	@was_busy: out parameter, indicates whether any port was busy
 *
 *	Acquire legacy ATA resources for the first two ports of @host
 *	and initialize it accordingly.  Ports marked dummy are skipped
 *	and resource acquistion failure makes the port dummy.
 *
 *	LOCKING:
 *	Inherited from calling layer (may sleep).
 *
 *	RETURNS:
 *	0 if at least one port is initialized, -ENODEV if no port is
 *	available.
 */
static int ata_init_legacy_host(struct ata_host *host, int *was_busy)
{
	struct device *gdev = host->dev;
	struct ata_legacy_devres *legacy_dr;
	int i, rc;

	if (!devres_open_group(gdev, NULL, GFP_KERNEL))
		return -ENOMEM;

	rc = -ENOMEM;
	legacy_dr = devres_alloc(ata_legacy_release, sizeof(*legacy_dr),
				 GFP_KERNEL);
	if (!legacy_dr)
		goto err_out;
	devres_add(gdev, legacy_dr);

	for (i = 0; i < 2; i++) {
		if (ata_port_is_dummy(host->ports[i]))
			continue;

		rc = ata_init_legacy_port(host->ports[i], legacy_dr);
		if (rc == 0)
			legacy_dr->mask |= 1 << i;
		else {
			if (rc == -EBUSY)
				(*was_busy)++;
			host->ports[i]->ops = &ata_dummy_port_ops;
		}
	}

	if (!legacy_dr->mask) {
		dev_printk(KERN_ERR, gdev, "no available legacy port\n");
		return -ENODEV;
	}

	devres_remove_group(gdev, NULL);
	return 0;

 err_out:
	devres_release_group(gdev, NULL);
	return rc;
}

/**
 *	ata_request_legacy_irqs - request legacy ATA IRQs
 *	@host: target ATA host
 *	@handler: array of IRQ handlers
 *	@irq_flags: array of IRQ flags
 *	@dev_id: array of IRQ dev_ids
 *
 *	Request legacy IRQs for non-dummy legacy ports in @host.  All
 *	IRQ parameters are passed as array to allow ports to have
 *	separate IRQ handlers.
 *
 *	LOCKING:
 *	Inherited from calling layer (may sleep).
 *
 *	RETURNS:
 *	0 on success, -errno otherwise.
 */
static int ata_request_legacy_irqs(struct ata_host *host,
				   irq_handler_t const *handler,
				   const unsigned int *irq_flags,
				   void * const *dev_id)
{
	struct device *gdev = host->dev;
	struct ata_legacy_devres *legacy_dr;
	int i, rc;

	legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL);
	BUG_ON(!legacy_dr);

	for (i = 0; i < 2; i++) {
		unsigned int irq;

		/* FIXME: ATA_*_IRQ() should take generic device not pci_dev */
		if (i == 0)
			irq = ATA_PRIMARY_IRQ(to_pci_dev(gdev));
		else
			irq = ATA_SECONDARY_IRQ(to_pci_dev(gdev));

		if (!(legacy_dr->mask & (1 << i)))
			continue;

		if (!handler[i]) {
			dev_printk(KERN_ERR, gdev,
				   "NULL handler specified for port %d\n", i);
			rc = -EINVAL;
			goto err_out;
		}

		rc = request_irq(irq, handler[i], irq_flags[i], DRV_NAME,
				 dev_id[i]);
		if (rc) {
			dev_printk(KERN_ERR, gdev,
				"irq %u request failed (errno=%d)\n", irq, rc);
			goto err_out;
		}

		/* record irq allocation in legacy_dr */
		legacy_dr->irq[i] = irq;
		legacy_dr->irq_dev_id[i] = dev_id[i];

		/* only used to print info */
		if (i == 0)
			host->irq = irq;
		else
			host->irq2 = irq;
	}

	return 0;

 err_out:
	ata_legacy_free_irqs(legacy_dr);
	return rc;
}

/**
 *	ata_pci_init_one - Initialize/register PCI IDE host controller
 *	@pdev: Controller to be initialized
@@ -1029,35 +818,11 @@ int ata_pci_init_one(struct pci_dev *pdev,
#endif
	}

	/* alloc and init host */
	host = ata_host_alloc_pinfo(dev, ppi, 2);
	if (!host) {
		dev_printk(KERN_ERR, &pdev->dev,
			   "failed to allocate ATA host\n");
		rc = -ENOMEM;
		goto err_out;
	}

	if (!legacy_mode) {
		rc = ata_pci_init_native_host(host);
		if (rc)
			goto err_out;
	} else {
		int was_busy = 0;

		rc = ata_init_legacy_host(host, &was_busy);
		if (was_busy)
			pcim_pin_device(pdev);
	/* prepare host */
	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
	if (rc)
		goto err_out;

		/* request respective PCI regions, may fail */
		rc = pci_request_region(pdev, 1, DRV_NAME);
		rc = pci_request_region(pdev, 3, DRV_NAME);
	}

	/* init BMDMA, may fail */
	ata_pci_init_bmdma(host);
	pci_set_master(pdev);

	/* start host and request IRQ */
@@ -1068,17 +833,28 @@ int ata_pci_init_one(struct pci_dev *pdev,
	if (!legacy_mode) {
		rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
				      IRQF_SHARED, DRV_NAME, host);
		if (rc)
			goto err_out;
		host->irq = pdev->irq;
	} else {
		irq_handler_t handler[2] = { host->ops->irq_handler,
					     host->ops->irq_handler };
		unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED };
		void *dev_id[2] = { host, host };

		rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id);
		if (!ata_port_is_dummy(host->ports[0])) {
			host->irq = ATA_PRIMARY_IRQ(pdev);
			rc = devm_request_irq(dev, host->irq,
					      pi->port_ops->irq_handler,
					      IRQF_SHARED, DRV_NAME, host);
			if (rc)
				goto err_out;
		}

		if (!ata_port_is_dummy(host->ports[1])) {
			host->irq2 = ATA_SECONDARY_IRQ(pdev);
			rc = devm_request_irq(dev, host->irq2,
					      pi->port_ops->irq_handler,
					      IRQF_SHARED, DRV_NAME, host);
			if (rc)
				goto err_out;
		}
	}

	/* register */
	rc = ata_host_register(host, pi->sht);
Loading