Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 158185
b: refs/heads/master
c: 70aedd2
h: refs/heads/master
i:
  158183: 063e138
v: v3
  • Loading branch information
Thomas Gleixner committed Aug 17, 2009
1 parent c6f5120 commit 21c1792
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b25c340c195447afb1860da580fe2a85a6b652c5
refs/heads/master: 70aedd24d20e75198f5a0b11750faabbb56924e2
6 changes: 6 additions & 0 deletions trunk/include/linux/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ struct msi_desc;
* @set_type: set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
* @set_wake: enable/disable power-management wake-on of an IRQ
*
* @bus_lock: function to lock access to slow bus (i2c) chips
* @bus_sync_unlock: function to sync and unlock slow bus (i2c) chips
*
* @release: release function solely used by UML
* @typename: obsoleted by name, kept as migration helper
*/
Expand All @@ -124,6 +127,9 @@ struct irq_chip {
int (*set_type)(unsigned int irq, unsigned int flow_type);
int (*set_wake)(unsigned int irq, unsigned int on);

void (*bus_lock)(unsigned int irq);
void (*bus_sync_unlock)(unsigned int irq);

/* Currently used only by UML, might disappear one day.*/
#ifdef CONFIG_IRQ_RELEASE_METHOD
void (*release)(unsigned int irq, void *dev_id);
Expand Down
2 changes: 2 additions & 0 deletions trunk/kernel/irq/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
desc->chip = &dummy_irq_chip;
}

chip_bus_lock(irq, desc);
spin_lock_irqsave(&desc->lock, flags);

/* Uninstall? */
Expand All @@ -599,6 +600,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
desc->chip->startup(irq);
}
spin_unlock_irqrestore(&desc->lock, flags);
chip_bus_sync_unlock(irq, desc);
}
EXPORT_SYMBOL_GPL(__set_irq_handler);

Expand Down
13 changes: 13 additions & 0 deletions trunk/kernel/irq/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ extern int irq_select_affinity_usr(unsigned int irq);

extern void irq_set_thread_affinity(struct irq_desc *desc);

/* Inline functions for support of irq chips on slow busses */
static inline void chip_bus_lock(unsigned int irq, struct irq_desc *desc)
{
if (unlikely(desc->chip->bus_lock))
desc->chip->bus_lock(irq);
}

static inline void chip_bus_sync_unlock(unsigned int irq, struct irq_desc *desc)
{
if (unlikely(desc->chip->bus_sync_unlock))
desc->chip->bus_sync_unlock(irq);
}

/*
* Debugging printout:
*/
Expand Down
19 changes: 18 additions & 1 deletion trunk/kernel/irq/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,11 @@ void disable_irq_nosync(unsigned int irq)
if (!desc)
return;

chip_bus_lock(irq, desc);
spin_lock_irqsave(&desc->lock, flags);
__disable_irq(desc, irq, false);
spin_unlock_irqrestore(&desc->lock, flags);
chip_bus_sync_unlock(irq, desc);
}
EXPORT_SYMBOL(disable_irq_nosync);

Expand Down Expand Up @@ -294,7 +296,8 @@ void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
* matches the last disable, processing of interrupts on this
* IRQ line is re-enabled.
*
* This function may be called from IRQ context.
* This function may be called from IRQ context only when
* desc->chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
*/
void enable_irq(unsigned int irq)
{
Expand All @@ -304,9 +307,11 @@ void enable_irq(unsigned int irq)
if (!desc)
return;

chip_bus_lock(irq, desc);
spin_lock_irqsave(&desc->lock, flags);
__enable_irq(desc, irq, false);
spin_unlock_irqrestore(&desc->lock, flags);
chip_bus_sync_unlock(irq, desc);
}
EXPORT_SYMBOL(enable_irq);

Expand Down Expand Up @@ -468,12 +473,14 @@ static int irq_wait_for_interrupt(struct irqaction *action)
*/
static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
{
chip_bus_lock(irq, desc);
spin_lock_irq(&desc->lock);
if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
desc->status &= ~IRQ_MASKED;
desc->chip->unmask(irq);
}
spin_unlock_irq(&desc->lock);
chip_bus_sync_unlock(irq, desc);
}

#ifdef CONFIG_SMP
Expand Down Expand Up @@ -904,7 +911,14 @@ EXPORT_SYMBOL_GPL(remove_irq);
*/
void free_irq(unsigned int irq, void *dev_id)
{
struct irq_desc *desc = irq_to_desc(irq);

if (!desc)
return;

chip_bus_lock(irq, desc);
kfree(__free_irq(irq, dev_id));
chip_bus_sync_unlock(irq, desc);
}
EXPORT_SYMBOL(free_irq);

Expand Down Expand Up @@ -1011,7 +1025,10 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
action->name = devname;
action->dev_id = dev_id;

chip_bus_lock(irq, desc);
retval = __setup_irq(irq, desc, action);
chip_bus_sync_unlock(irq, desc);

if (retval)
kfree(action);

Expand Down

0 comments on commit 21c1792

Please sign in to comment.