aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-09-25 14:37:52 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-09-25 14:37:52 +0100
commit6a2722c6753efe3c071027634e1b8c99c299e0a8 (patch)
tree6929316f37612f724a6ca812eef891c15ff63105
parent0ae658ea9f3e26ec9ea613a1d5e85d8bf3296277 (diff)
downloadxen-6a2722c6753efe3c071027634e1b8c99c299e0a8.tar.gz
xen-6a2722c6753efe3c071027634e1b8c99c299e0a8.tar.bz2
xen-6a2722c6753efe3c071027634e1b8c99c299e0a8.zip
x86: Clean up and fix 18539:31f09a5e24cf8
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/ia64/xen/irq.c12
-rw-r--r--xen/arch/x86/irq.c101
-rw-r--r--xen/arch/x86/physdev.c2
-rw-r--r--xen/common/event_channel.c3
-rw-r--r--xen/include/asm-x86/irq.h2
-rw-r--r--xen/include/xen/irq.h2
6 files changed, 75 insertions, 47 deletions
diff --git a/xen/arch/ia64/xen/irq.c b/xen/arch/ia64/xen/irq.c
index 156bd8a55b..2c250148c5 100644
--- a/xen/arch/ia64/xen/irq.c
+++ b/xen/arch/ia64/xen/irq.c
@@ -459,12 +459,12 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
return rc;
}
-int pirq_guest_unbind(struct domain *d, int irq)
+void pirq_guest_unbind(struct domain *d, int irq)
{
irq_desc_t *desc = &irq_desc[irq];
irq_guest_action_t *action;
unsigned long flags;
- int i, rc = 0;
+ int i;
spin_lock_irqsave(&desc->lock, flags);
@@ -472,11 +472,7 @@ int pirq_guest_unbind(struct domain *d, int irq)
for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
continue;
- if ( i == action->nr_guests )
- {
- rc = -EINVAL;
- goto out;
- }
+ BUG_ON(i == action->nr_guests);
memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
action->nr_guests--;
@@ -496,9 +492,7 @@ int pirq_guest_unbind(struct domain *d, int irq)
desc->handler->shutdown(irq);
}
- out:
spin_unlock_irqrestore(&desc->lock, flags);
- return rc;
}
void
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index e22ccec856..d8cb9cc9d3 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -508,14 +508,14 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
unsigned int vector;
irq_desc_t *desc;
irq_guest_action_t *action;
- unsigned long flags;
int rc = 0;
cpumask_t cpumask = CPU_MASK_NONE;
WARN_ON(!spin_is_locked(&v->domain->evtchn_lock));
+ BUG_ON(!local_irq_is_enabled());
retry:
- desc = domain_spin_lock_irq_desc(v->domain, irq, &flags);
+ desc = domain_spin_lock_irq_desc(v->domain, irq, NULL);
if ( desc == NULL )
return -EINVAL;
@@ -575,7 +575,7 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
*/
ASSERT(action->ack_type == ACKTYPE_EOI);
ASSERT(desc->status & IRQ_DISABLED);
- spin_unlock_irqrestore(&desc->lock, flags);
+ spin_unlock_irq(&desc->lock);
cpu_relax();
goto retry;
}
@@ -591,43 +591,25 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
action->guest[action->nr_guests++] = v->domain;
out:
- spin_unlock_irqrestore(&desc->lock, flags);
+ spin_unlock_irq(&desc->lock);
return rc;
}
-int pirq_guest_unbind(struct domain *d, int irq)
+static void __pirq_guest_unbind(struct domain *d, int irq, irq_desc_t *desc)
{
- int vector;
- irq_desc_t *desc;
+ unsigned int vector;
irq_guest_action_t *action;
cpumask_t cpu_eoi_map;
- unsigned long flags;
- int i, rc = 0;
-
- WARN_ON(!spin_is_locked(&d->evtchn_lock));
+ int i;
- desc = domain_spin_lock_irq_desc(d, irq, &flags);
- if ( unlikely(desc == NULL) )
- {
- if ( (vector = -domain_irq_to_vector(d, irq)) == 0 )
- return -EINVAL;
- BUG_ON(vector <= 0);
- desc = &irq_desc[vector];
- spin_lock_irqsave(&desc->lock, flags);
- d->arch.pirq_vector[irq] = d->arch.vector_pirq[vector] = 0;
- goto out;
- }
+ BUG_ON(!(desc->status & IRQ_GUEST));
action = (irq_guest_action_t *)desc->action;
vector = desc - irq_desc;
for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
continue;
- if ( i == action->nr_guests )
- {
- rc = -EINVAL;
- goto out;
- }
+ BUG_ON(i == action->nr_guests);
memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
action->nr_guests--;
@@ -645,9 +627,9 @@ int pirq_guest_unbind(struct domain *d, int irq)
(action->nr_guests != 0) )
{
cpu_eoi_map = action->cpu_eoi_map;
- spin_unlock_irqrestore(&desc->lock, flags);
+ spin_unlock_irq(&desc->lock);
on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 0);
- spin_lock_irqsave(&desc->lock, flags);
+ spin_lock_irq(&desc->lock);
}
break;
}
@@ -659,7 +641,7 @@ int pirq_guest_unbind(struct domain *d, int irq)
BUG_ON(test_bit(irq, d->pirq_mask));
if ( action->nr_guests != 0 )
- goto out;
+ return;
BUG_ON(action->in_flight != 0);
@@ -679,9 +661,9 @@ int pirq_guest_unbind(struct domain *d, int irq)
if ( !cpus_empty(cpu_eoi_map) )
{
BUG_ON(action->ack_type != ACKTYPE_EOI);
- spin_unlock_irqrestore(&desc->lock, flags);
+ spin_unlock_irq(&desc->lock);
on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 1);
- spin_lock_irqsave(&desc->lock, flags);
+ spin_lock_irq(&desc->lock);
}
BUG_ON(!cpus_empty(action->cpu_eoi_map));
@@ -692,10 +674,61 @@ int pirq_guest_unbind(struct domain *d, int irq)
desc->status &= ~IRQ_INPROGRESS;
kill_timer(&irq_guest_eoi_timer[vector]);
desc->handler->shutdown(vector);
+}
+
+void pirq_guest_unbind(struct domain *d, int irq)
+{
+ irq_desc_t *desc;
+ int vector;
+
+ WARN_ON(!spin_is_locked(&d->evtchn_lock));
+
+ BUG_ON(!local_irq_is_enabled());
+ desc = domain_spin_lock_irq_desc(d, irq, NULL);
+
+ if ( desc == NULL )
+ {
+ vector = -domain_irq_to_vector(d, irq);
+ BUG_ON(vector <= 0);
+ desc = &irq_desc[vector];
+ spin_lock_irq(&desc->lock);
+ d->arch.pirq_vector[irq] = d->arch.vector_pirq[vector] = 0;
+ }
+ else
+ {
+ __pirq_guest_unbind(d, irq, desc);
+ }
+
+ spin_unlock_irq(&desc->lock);
+}
+
+int pirq_guest_force_unbind(struct domain *d, int irq)
+{
+ irq_desc_t *desc;
+ irq_guest_action_t *action;
+ int i, bound = 0;
+
+ WARN_ON(!spin_is_locked(&d->evtchn_lock));
+
+ BUG_ON(!local_irq_is_enabled());
+ desc = domain_spin_lock_irq_desc(d, irq, NULL);
+ BUG_ON(desc == NULL);
+
+ if ( !(desc->status & IRQ_GUEST) )
+ goto out;
+
+ action = (irq_guest_action_t *)desc->action;
+ for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
+ continue;
+ if ( i == action->nr_guests )
+ goto out;
+
+ bound = 1;
+ __pirq_guest_unbind(d, irq, desc);
out:
- spin_unlock_irqrestore(&desc->lock, flags);
- return rc;
+ spin_unlock_irq(&desc->lock);
+ return bound;
}
extern void dump_ioapic_irq_info(void);
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index 18e6b26279..11c97ef9ad 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -146,7 +146,7 @@ static int unmap_domain_pirq(struct domain *d, int pirq)
goto done;
}
- forced_unbind = (pirq_guest_unbind(d, pirq) == 0);
+ forced_unbind = pirq_guest_force_unbind(d, pirq);
if ( forced_unbind )
dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n",
d->domain_id, pirq);
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index f7a0e87bc7..006d5eca3a 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -387,8 +387,7 @@ static long __evtchn_close(struct domain *d1, int port1)
break;
case ECS_PIRQ:
- if ( pirq_guest_unbind(d1, chn1->u.pirq) != 0 )
- BUG();
+ pirq_guest_unbind(d1, chn1->u.pirq);
d1->pirq_to_evtchn[chn1->u.pirq] = 0;
break;
diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h
index 692823d0b1..223ab8f749 100644
--- a/xen/include/asm-x86/irq.h
+++ b/xen/include/asm-x86/irq.h
@@ -55,4 +55,6 @@ int pirq_shared(struct domain *d , int irq);
#define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[(irq)])
#define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[(vec)])
+int pirq_guest_force_unbind(struct domain *d, int irq);
+
#endif /* _ASM_HW_IRQ_H */
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index 7f0acb52dd..71f17d6e87 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -77,7 +77,7 @@ struct vcpu;
extern int pirq_guest_eoi(struct domain *d, int irq);
extern int pirq_guest_unmask(struct domain *d);
extern int pirq_guest_bind(struct vcpu *v, int irq, int will_share);
-extern int pirq_guest_unbind(struct domain *d, int irq);
+extern void pirq_guest_unbind(struct domain *d, int irq);
static inline void set_native_irq_info(int irq, cpumask_t mask)
{