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

Commit ae86afae authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz
Browse files

ide: use per-port IRQ handlers



Use hwif instead of hwgroup as {request,free}_irq()'s cookie,
teach ide_intr() to return early for non-active serialized ports,
modify unexpected_intr() accordingly and then use per-port IRQ
handlers instead of per-hwgroup ones.

Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent bd53cbcc
Loading
Loading
Loading
Loading
+23 −35
Original line number Original line Diff line number Diff line
@@ -723,7 +723,7 @@ void do_ide_request(struct request_queue *q)
	spin_unlock_irq(q->queue_lock);
	spin_unlock_irq(q->queue_lock);
	spin_lock_irq(&hwgroup->lock);
	spin_lock_irq(&hwgroup->lock);


	if (!ide_lock_hwgroup(hwgroup)) {
	if (!ide_lock_hwgroup(hwgroup, hwif)) {
		ide_hwif_t *prev_port;
		ide_hwif_t *prev_port;
repeat:
repeat:
		prev_port = hwif->host->cur_port;
		prev_port = hwif->host->cur_port;
@@ -1002,44 +1002,30 @@ void ide_timer_expiry (unsigned long data)
 *	before completing the issuance of any new drive command, so we will not
 *	before completing the issuance of any new drive command, so we will not
 *	be accidentally invoked as a result of any valid command completion
 *	be accidentally invoked as a result of any valid command completion
 *	interrupt.
 *	interrupt.
 *
 *	Note that we must walk the entire hwgroup here. We know which hwif
 *	is doing the current command, but we don't know which hwif burped
 *	mysteriously.
 */
 */


static void unexpected_intr(int irq, ide_hwif_t *hwif)
static void unexpected_intr(int irq, ide_hwif_t *hwif)
{
{
	ide_hwgroup_t *hwgroup = hwif->hwgroup;
	u8 stat = hwif->tp_ops->read_status(hwif);
	u8 stat;

	/*
	 * handle the unexpected interrupt
	 */
	do {
		if (hwif->irq == irq) {
			stat = hwif->tp_ops->read_status(hwif);


	if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
	if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
		/* Try to not flood the console with msgs */
		/* Try to not flood the console with msgs */
		static unsigned long last_msgtime, count;
		static unsigned long last_msgtime, count;
		++count;
		++count;

		if (time_after(jiffies, last_msgtime + HZ)) {
		if (time_after(jiffies, last_msgtime + HZ)) {
			last_msgtime = jiffies;
			last_msgtime = jiffies;
					printk(KERN_ERR "%s%s: unexpected interrupt, "
			printk(KERN_ERR "%s: unexpected interrupt, "
				"status=0x%02x, count=%ld\n",
				"status=0x%02x, count=%ld\n",
						hwif->name,
				hwif->name, stat, count);
						(hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count);
		}
		}
	}
	}
}
}
	} while ((hwif = hwif->next) != hwgroup->hwif);
}


/**
/**
 *	ide_intr	-	default IDE interrupt handler
 *	ide_intr	-	default IDE interrupt handler
 *	@irq: interrupt number
 *	@irq: interrupt number
 *	@dev_id: hwif group
 *	@dev_id: hwif
 *	@regs: unused weirdness from the kernel irq layer
 *	@regs: unused weirdness from the kernel irq layer
 *
 *
 *	This is the default IRQ handler for the IDE layer. You should
 *	This is the default IRQ handler for the IDE layer. You should
@@ -1063,17 +1049,19 @@ static void unexpected_intr(int irq, ide_hwif_t *hwif)
 
 
irqreturn_t ide_intr (int irq, void *dev_id)
irqreturn_t ide_intr (int irq, void *dev_id)
{
{
	unsigned long flags;
	ide_hwif_t *hwif = (ide_hwif_t *)dev_id;
	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
	ide_hwgroup_t *hwgroup = hwif->hwgroup;
	ide_hwif_t *hwif = hwgroup->hwif;
	ide_drive_t *uninitialized_var(drive);
	ide_drive_t *uninitialized_var(drive);
	ide_handler_t *handler;
	ide_handler_t *handler;
	unsigned long flags;
	ide_startstop_t startstop;
	ide_startstop_t startstop;
	irqreturn_t irq_ret = IRQ_NONE;
	irqreturn_t irq_ret = IRQ_NONE;
	int plug_device = 0;
	int plug_device = 0;


	if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE)
	if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
		hwif = hwif->host->cur_port;
		if (hwif != hwif->host->cur_port)
			goto out_early;
	}


	spin_lock_irqsave(&hwgroup->lock, flags);
	spin_lock_irqsave(&hwgroup->lock, flags);


@@ -1172,7 +1160,7 @@ out_handled:
	irq_ret = IRQ_HANDLED;
	irq_ret = IRQ_HANDLED;
out:
out:
	spin_unlock_irqrestore(&hwgroup->lock, flags);
	spin_unlock_irqrestore(&hwgroup->lock, flags);

out_early:
	if (plug_device)
	if (plug_device)
		ide_plug_device(drive);
		ide_plug_device(drive);


+8 −13
Original line number Original line Diff line number Diff line
@@ -1022,6 +1022,7 @@ static int init_irq (ide_hwif_t *hwif)
	unsigned int index;
	unsigned int index;
	ide_hwgroup_t *hwgroup;
	ide_hwgroup_t *hwgroup;
	ide_hwif_t *match = NULL;
	ide_hwif_t *match = NULL;
	int sa = 0;


	mutex_lock(&ide_cfg_mtx);
	mutex_lock(&ide_cfg_mtx);
	hwif->hwgroup = NULL;
	hwif->hwgroup = NULL;
@@ -1076,11 +1077,6 @@ static int init_irq (ide_hwif_t *hwif)


	ide_ports[hwif->index] = hwif;
	ide_ports[hwif->index] = hwif;


	/*
	 * Allocate the irq, if not already obtained for another hwif
	 */
	if (!match || match->irq != hwif->irq) {
		int sa = 0;
#if defined(__mc68000__)
#if defined(__mc68000__)
	sa = IRQF_SHARED;
	sa = IRQF_SHARED;
#endif /* __mc68000__ */
#endif /* __mc68000__ */
@@ -1091,9 +1087,8 @@ static int init_irq (ide_hwif_t *hwif)
	if (io_ports->ctl_addr)
	if (io_ports->ctl_addr)
		hwif->tp_ops->set_irq(hwif, 1);
		hwif->tp_ops->set_irq(hwif, 1);


		if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
	if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif))
		goto out_unlink;
		goto out_unlink;
	}


	if (!hwif->rqsize) {
	if (!hwif->rqsize) {
		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+1 −16
Original line number Original line Diff line number Diff line
@@ -175,10 +175,6 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices);


void ide_unregister(ide_hwif_t *hwif)
void ide_unregister(ide_hwif_t *hwif)
{
{
	ide_hwif_t *g;
	ide_hwgroup_t *hwgroup;
	int irq_count = 0;

	BUG_ON(in_interrupt());
	BUG_ON(in_interrupt());
	BUG_ON(irqs_disabled());
	BUG_ON(irqs_disabled());


@@ -191,18 +187,7 @@ void ide_unregister(ide_hwif_t *hwif)


	ide_proc_unregister_port(hwif);
	ide_proc_unregister_port(hwif);


	hwgroup = hwif->hwgroup;
	free_irq(hwif->irq, hwif);
	/*
	 * free the irq if we were the only hwif using it
	 */
	g = hwgroup->hwif;
	do {
		if (g->irq == hwif->irq)
			++irq_count;
		g = g->next;
	} while (g != hwgroup->hwif);
	if (irq_count == 1)
		free_irq(hwif->irq, hwgroup);


	ide_remove_port_from_hwgroup(hwif);
	ide_remove_port_from_hwgroup(hwif);


+2 −2
Original line number Original line Diff line number Diff line
@@ -1274,14 +1274,14 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
extern void ide_timer_expiry(unsigned long);
extern void ide_timer_expiry(unsigned long);
extern irqreturn_t ide_intr(int irq, void *dev_id);
extern irqreturn_t ide_intr(int irq, void *dev_id);


static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup)
static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup, ide_hwif_t *hwif)
{
{
	if (hwgroup->busy)
	if (hwgroup->busy)
		return 1;
		return 1;


	hwgroup->busy = 1;
	hwgroup->busy = 1;
	/* for atari only */
	/* for atari only */
	ide_get_lock(ide_intr, hwgroup);
	ide_get_lock(ide_intr, hwif);


	return 0;
	return 0;
}
}