aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-04-08 11:01:17 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-04-08 11:01:17 +0100
commitee29f146c33b704a5e256fe0a36b851d021c1225 (patch)
tree5d1240a887a0ac9708e8650e73e0b75b95643d94
parentb766b4774afbaf01a0b2291e4d9add1df953dc11 (diff)
downloadxen-ee29f146c33b704a5e256fe0a36b851d021c1225.tar.gz
xen-ee29f146c33b704a5e256fe0a36b851d021c1225.tar.bz2
xen-ee29f146c33b704a5e256fe0a36b851d021c1225.zip
Fix remove_pin_at_irq(), introduced with changeset
9586:f84a333d8aa6e1a25e2b73b07610e95007267f6a. Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r--xen/arch/x86/io_apic.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index ca180d3bf7..97aae7a77d 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -110,7 +110,6 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
static void remove_pin_at_irq(unsigned int irq, int apic, int pin)
{
struct irq_pin_list *entry, *prev;
- int idx;
for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
if ((entry->apic == apic) && (entry->pin == pin))
@@ -119,18 +118,24 @@ static void remove_pin_at_irq(unsigned int irq, int apic, int pin)
BUG();
}
- entry->pin = -1;
- entry->apic = -1;
+ entry->pin = entry->apic = -1;
- idx = entry - irq_2_pin;
- if (idx >= NR_IRQS) {
- while (prev->next != idx)
+ if (entry != &irq_2_pin[irq]) {
+ /* Removed entry is not at head of list. */
+ prev = &irq_2_pin[irq];
+ while (&irq_2_pin[prev->next] != entry)
prev = &irq_2_pin[prev->next];
prev->next = entry->next;
entry->next = irq_2_pin_free_entry;
- irq_2_pin_free_entry = idx;
- } else {
- entry->next = 0;
+ irq_2_pin_free_entry = entry - irq_2_pin;
+ } else if (entry->next != 0) {
+ /* Removed entry is at head of multi-item list. */
+ prev = entry;
+ entry = &irq_2_pin[entry->next];
+ *prev = *entry;
+ entry->pin = entry->apic = -1;
+ entry->next = irq_2_pin_free_entry;
+ irq_2_pin_free_entry = entry - irq_2_pin;
}
}