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

Commit e5217fb8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branches 'irq-cleanup-for-linus' and 'irq-fixes-for-linus' of...

Merge branches 'irq-cleanup-for-linus' and 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'irq-cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  vlynq: Convert irq functions

* 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  genirq; Fix cleanup fallout
  genirq: Fix typo and remove unused variable
  genirq: Fix new kernel-doc warnings
  genirq: Add setter for AFFINITY_SET in irq_data state
  genirq: Provide setter inline for IRQD_IRQ_INPROGRESS
  genirq: Remove handle_IRQ_event
  arm: Ns9xxx: Remove private irq flow handler
  powerpc: cell: Use the core flow handler
  genirq: Provide edge_eoi flow handler
  genirq: Move INPROGRESS, MASKED and DISABLED state flags to irq_data
  genirq: Split irq_set_affinity() so it can be called with lock held.
  genirq: Add chip flag for restricting cpu_on/offline calls
  genirq: Add chip hooks for taking CPUs on/off line.
  genirq: Add irq disabled flag to irq_data state
  genirq: Reserve the irq when calling irq_set_chip()
Loading
Loading
Loading
Loading
+4 −54
Original line number Diff line number Diff line
@@ -31,17 +31,11 @@ static void ns9xxx_mask_irq(struct irq_data *d)
	__raw_writel(ic, SYS_IC(prio / 4));
}

static void ns9xxx_ack_irq(struct irq_data *d)
static void ns9xxx_eoi_irq(struct irq_data *d)
{
	__raw_writel(0, SYS_ISRADDR);
}

static void ns9xxx_maskack_irq(struct irq_data *d)
{
	ns9xxx_mask_irq(d);
	ns9xxx_ack_irq(d);
}

static void ns9xxx_unmask_irq(struct irq_data *d)
{
	/* XXX: better use cpp symbols */
@@ -52,56 +46,11 @@ static void ns9xxx_unmask_irq(struct irq_data *d)
}

static struct irq_chip ns9xxx_chip = {
	.irq_ack	= ns9xxx_ack_irq,
	.irq_eoi	= ns9xxx_eoi_irq,
	.irq_mask	= ns9xxx_mask_irq,
	.irq_mask_ack	= ns9xxx_maskack_irq,
	.irq_unmask	= ns9xxx_unmask_irq,
};

#if 0
#define handle_irq handle_level_irq
#else
static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
{
	struct irqaction *action;
	irqreturn_t action_ret;

	raw_spin_lock(&desc->lock);

	BUG_ON(desc->status & IRQ_INPROGRESS);

	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
	kstat_incr_irqs_this_cpu(irq, desc);

	action = desc->action;
	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
		goto out_mask;

	desc->status |= IRQ_INPROGRESS;
	raw_spin_unlock(&desc->lock);

	action_ret = handle_IRQ_event(irq, action);

	/* XXX: There is no direct way to access noirqdebug, so check
	 * unconditionally for spurious irqs...
	 * Maybe this function should go to kernel/irq/chip.c? */
	note_interrupt(irq, desc, action_ret);

	raw_spin_lock(&desc->lock);
	desc->status &= ~IRQ_INPROGRESS;

	if (desc->status & IRQ_DISABLED)
out_mask:
		desc->irq_data.chip->irq_mask(&desc->irq_data);

	/* ack unconditionally to unmask lower prio irqs */
	desc->irq_data.chip->irq_ack(&desc->irq_data);

	raw_spin_unlock(&desc->lock);
}
#define handle_irq handle_prio_irq
#endif

void __init ns9xxx_init_irq(void)
{
	int i;
@@ -119,7 +68,8 @@ void __init ns9xxx_init_irq(void)

	for (i = 0; i <= 31; ++i) {
		set_irq_chip(i, &ns9xxx_chip);
		set_irq_handler(i, handle_irq);
		set_irq_handler(i, handle_fasteoi_irq);
		set_irq_flags(i, IRQF_VALID);
		irq_set_status_flags(i, IRQ_LEVEL);
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ config PPC_CELL_COMMON
	select PPC_INDIRECT_IO
	select PPC_NATIVE
	select PPC_RTAS
	select IRQ_EDGE_EOI_HANDLER

config PPC_CELL_NATIVE
	bool
+1 −49
Original line number Diff line number Diff line
@@ -235,54 +235,6 @@ static int iic_host_match(struct irq_host *h, struct device_node *node)
				    "IBM,CBEA-Internal-Interrupt-Controller");
}

extern int noirqdebug;

static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
{
	struct irq_chip *chip = get_irq_desc_chip(desc);

	raw_spin_lock(&desc->lock);

	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);

	/*
	 * If we're currently running this IRQ, or its disabled,
	 * we shouldn't process the IRQ. Mark it pending, handle
	 * the necessary masking and go out
	 */
	if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
		    !desc->action)) {
		desc->status |= IRQ_PENDING;
		goto out_eoi;
	}

	kstat_incr_irqs_this_cpu(irq, desc);

	/* Mark the IRQ currently in progress.*/
	desc->status |= IRQ_INPROGRESS;

	do {
		struct irqaction *action = desc->action;
		irqreturn_t action_ret;

		if (unlikely(!action))
			goto out_eoi;

		desc->status &= ~IRQ_PENDING;
		raw_spin_unlock(&desc->lock);
		action_ret = handle_IRQ_event(irq, action);
		if (!noirqdebug)
			note_interrupt(irq, desc, action_ret);
		raw_spin_lock(&desc->lock);

	} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);

	desc->status &= ~IRQ_INPROGRESS;
out_eoi:
	chip->irq_eoi(&desc->irq_data);
	raw_spin_unlock(&desc->lock);
}

static int iic_host_map(struct irq_host *h, unsigned int virq,
			irq_hw_number_t hw)
{
@@ -295,7 +247,7 @@ static int iic_host_map(struct irq_host *h, unsigned int virq,
					 handle_iic_irq);
		break;
	default:
		set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq);
		set_irq_chip_and_handler(virq, &iic_chip, handle_edge_eoi_irq);
	}
	return 0;
}
+31 −33
Original line number Diff line number Diff line
@@ -135,40 +135,40 @@ static void vlynq_reset(struct vlynq_device *dev)
	msleep(5);
}

static void vlynq_irq_unmask(unsigned int irq)
static void vlynq_irq_unmask(struct irq_data *d)
{
	u32 val;
	struct vlynq_device *dev = get_irq_chip_data(irq);
	struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
	int virq;
	u32 val;

	BUG_ON(!dev);
	virq = irq - dev->irq_start;
	virq = d->irq - dev->irq_start;
	val = readl(&dev->remote->int_device[virq >> 2]);
	val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq);
	writel(val, &dev->remote->int_device[virq >> 2]);
}

static void vlynq_irq_mask(unsigned int irq)
static void vlynq_irq_mask(struct irq_data *d)
{
	u32 val;
	struct vlynq_device *dev = get_irq_chip_data(irq);
	struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
	int virq;
	u32 val;

	BUG_ON(!dev);
	virq = irq - dev->irq_start;
	virq = d->irq - dev->irq_start;
	val = readl(&dev->remote->int_device[virq >> 2]);
	val &= ~(VINT_ENABLE << VINT_OFFSET(virq));
	writel(val, &dev->remote->int_device[virq >> 2]);
}

static int vlynq_irq_type(unsigned int irq, unsigned int flow_type)
static int vlynq_irq_type(struct irq_data *d, unsigned int flow_type)
{
	u32 val;
	struct vlynq_device *dev = get_irq_chip_data(irq);
	struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
	int virq;
	u32 val;

	BUG_ON(!dev);
	virq = irq - dev->irq_start;
	virq = d->irq - dev->irq_start;
	val = readl(&dev->remote->int_device[virq >> 2]);
	switch (flow_type & IRQ_TYPE_SENSE_MASK) {
	case IRQ_TYPE_EDGE_RISING:
@@ -192,10 +192,9 @@ static int vlynq_irq_type(unsigned int irq, unsigned int flow_type)
	return 0;
}

static void vlynq_local_ack(unsigned int irq)
static void vlynq_local_ack(struct irq_data *d)
{
	struct vlynq_device *dev = get_irq_chip_data(irq);

	struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
	u32 status = readl(&dev->local->status);

	pr_debug("%s: local status: 0x%08x\n",
@@ -203,10 +202,9 @@ static void vlynq_local_ack(unsigned int irq)
	writel(status, &dev->local->status);
}

static void vlynq_remote_ack(unsigned int irq)
static void vlynq_remote_ack(struct irq_data *d)
{
	struct vlynq_device *dev = get_irq_chip_data(irq);

	struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
	u32 status = readl(&dev->remote->status);

	pr_debug("%s: remote status: 0x%08x\n",
@@ -238,23 +236,23 @@ static irqreturn_t vlynq_irq(int irq, void *dev_id)

static struct irq_chip vlynq_irq_chip = {
	.name = "vlynq",
	.unmask = vlynq_irq_unmask,
	.mask = vlynq_irq_mask,
	.set_type = vlynq_irq_type,
	.irq_unmask = vlynq_irq_unmask,
	.irq_mask = vlynq_irq_mask,
	.irq_set_type = vlynq_irq_type,
};

static struct irq_chip vlynq_local_chip = {
	.name = "vlynq local error",
	.unmask = vlynq_irq_unmask,
	.mask = vlynq_irq_mask,
	.ack = vlynq_local_ack,
	.irq_unmask = vlynq_irq_unmask,
	.irq_mask = vlynq_irq_mask,
	.irq_ack = vlynq_local_ack,
};

static struct irq_chip vlynq_remote_chip = {
	.name = "vlynq local error",
	.unmask = vlynq_irq_unmask,
	.mask = vlynq_irq_mask,
	.ack = vlynq_remote_ack,
	.irq_unmask = vlynq_irq_unmask,
	.irq_mask = vlynq_irq_mask,
	.irq_ack = vlynq_remote_ack,
};

static int vlynq_setup_irq(struct vlynq_device *dev)
@@ -291,17 +289,17 @@ static int vlynq_setup_irq(struct vlynq_device *dev)
	for (i = dev->irq_start; i <= dev->irq_end; i++) {
		virq = i - dev->irq_start;
		if (virq == dev->local_irq) {
			set_irq_chip_and_handler(i, &vlynq_local_chip,
			irq_set_chip_and_handler(i, &vlynq_local_chip,
						 handle_level_irq);
			set_irq_chip_data(i, dev);
			irq_set_chip_data(i, dev);
		} else if (virq == dev->remote_irq) {
			set_irq_chip_and_handler(i, &vlynq_remote_chip,
			irq_set_chip_and_handler(i, &vlynq_remote_chip,
						 handle_level_irq);
			set_irq_chip_data(i, dev);
			irq_set_chip_data(i, dev);
		} else {
			set_irq_chip_and_handler(i, &vlynq_irq_chip,
			irq_set_chip_and_handler(i, &vlynq_irq_chip,
						 handle_simple_irq);
			set_irq_chip_data(i, dev);
			irq_set_chip_data(i, dev);
			writel(0, &dev->remote->int_device[virq >> 2]);
		}
	}
+55 −4
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ struct msi_desc;
 * struct irq_data - per irq and irq chip data passed down to chip functions
 * @irq:		interrupt number
 * @node:		node index useful for balancing
 * @state_use_accessor: status information for irq chip functions.
 * @state_use_accessors: status information for irq chip functions.
 *			Use accessor functions to deal with it
 * @chip:		low level interrupt hardware access
 * @handler_data:	per-IRQ data for the irq_chip methods
@@ -174,6 +174,9 @@ struct irq_data {
 *				  from suspend
 * IRDQ_MOVE_PCNTXT		- Interrupt can be moved in process
 *				  context
 * IRQD_IRQ_DISABLED		- Disabled state of the interrupt
 * IRQD_IRQ_MASKED		- Masked state of the interrupt
 * IRQD_IRQ_INPROGRESS		- In progress state of the interrupt
 */
enum {
	IRQD_TRIGGER_MASK		= 0xf,
@@ -184,6 +187,9 @@ enum {
	IRQD_LEVEL			= (1 << 13),
	IRQD_WAKEUP_STATE		= (1 << 14),
	IRQD_MOVE_PCNTXT		= (1 << 15),
	IRQD_IRQ_DISABLED		= (1 << 16),
	IRQD_IRQ_MASKED			= (1 << 17),
	IRQD_IRQ_INPROGRESS		= (1 << 18),
};

static inline bool irqd_is_setaffinity_pending(struct irq_data *d)
@@ -206,6 +212,11 @@ static inline bool irqd_affinity_was_set(struct irq_data *d)
	return d->state_use_accessors & IRQD_AFFINITY_SET;
}

static inline void irqd_mark_affinity_was_set(struct irq_data *d)
{
	d->state_use_accessors |= IRQD_AFFINITY_SET;
}

static inline u32 irqd_get_trigger_type(struct irq_data *d)
{
	return d->state_use_accessors & IRQD_TRIGGER_MASK;
@@ -235,6 +246,36 @@ static inline bool irqd_can_move_in_process_context(struct irq_data *d)
	return d->state_use_accessors & IRQD_MOVE_PCNTXT;
}

static inline bool irqd_irq_disabled(struct irq_data *d)
{
	return d->state_use_accessors & IRQD_IRQ_DISABLED;
}

static inline bool irqd_irq_masked(struct irq_data *d)
{
	return d->state_use_accessors & IRQD_IRQ_MASKED;
}

static inline bool irqd_irq_inprogress(struct irq_data *d)
{
	return d->state_use_accessors & IRQD_IRQ_INPROGRESS;
}

/*
 * Functions for chained handlers which can be enabled/disabled by the
 * standard disable_irq/enable_irq calls. Must be called with
 * irq_desc->lock held.
 */
static inline void irqd_set_chained_irq_inprogress(struct irq_data *d)
{
	d->state_use_accessors |= IRQD_IRQ_INPROGRESS;
}

static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
{
	d->state_use_accessors &= ~IRQD_IRQ_INPROGRESS;
}

/**
 * struct irq_chip - hardware interrupt chip descriptor
 *
@@ -271,6 +312,8 @@ static inline bool irqd_can_move_in_process_context(struct irq_data *d)
 * @irq_set_wake:	enable/disable power-management wake-on of an IRQ
 * @irq_bus_lock:	function to lock access to slow bus (i2c) chips
 * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
 * @irq_cpu_online:	configure an interrupt source for a secondary CPU
 * @irq_cpu_offline:	un-configure an interrupt source for a secondary CPU
 * @irq_print_chip:	optional to print special chip info in show_interrupts
 * @flags:		chip specific flags
 *
@@ -319,6 +362,9 @@ struct irq_chip {
	void		(*irq_bus_lock)(struct irq_data *data);
	void		(*irq_bus_sync_unlock)(struct irq_data *data);

	void		(*irq_cpu_online)(struct irq_data *data);
	void		(*irq_cpu_offline)(struct irq_data *data);

	void		(*irq_print_chip)(struct irq_data *data, struct seq_file *p);

	unsigned long	flags;
@@ -335,11 +381,14 @@ struct irq_chip {
 * IRQCHIP_SET_TYPE_MASKED:	Mask before calling chip.irq_set_type()
 * IRQCHIP_EOI_IF_HANDLED:	Only issue irq_eoi() when irq was handled
 * IRQCHIP_MASK_ON_SUSPEND:	Mask non wake irqs in the suspend path
 * IRQCHIP_ONOFFLINE_ENABLED:	Only call irq_on/off_line callbacks
 *				when irq enabled
 */
enum {
	IRQCHIP_SET_TYPE_MASKED		= (1 <<  0),
	IRQCHIP_EOI_IF_HANDLED		= (1 <<  1),
	IRQCHIP_MASK_ON_SUSPEND		= (1 <<  2),
	IRQCHIP_ONOFFLINE_ENABLED	= (1 <<  3),
};

/* This include will go away once we isolated irq_desc usage to core code */
@@ -364,6 +413,10 @@ struct irqaction;
extern int setup_irq(unsigned int irq, struct irqaction *new);
extern void remove_irq(unsigned int irq, struct irqaction *act);

extern void irq_cpu_online(void);
extern void irq_cpu_offline(void);
extern int __irq_set_affinity_locked(struct irq_data *data,  const struct cpumask *cpumask);

#ifdef CONFIG_GENERIC_HARDIRQS

#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
@@ -380,9 +433,6 @@ static inline void irq_move_masked_irq(struct irq_data *data) { }

extern int no_irq_affinity;

/* Handle irq action chains: */
extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);

/*
 * Built-in IRQ handlers for various IRQ types,
 * callable via desc->handle_irq()
@@ -390,6 +440,7 @@ extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);
extern void handle_level_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
Loading