Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 282073
b: refs/heads/master
c: 420eb55
h: refs/heads/master
i:
  282071: 82a36a0
v: v3
  • Loading branch information
Daniel De Graaf authored and Konrad Rzeszutek Wilk committed Nov 21, 2011
1 parent 7902edd commit e81426d
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 3 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: 0cc678f850f2cba0cedbd133fcbbf175554cd6c6
refs/heads/master: 420eb554d5ee6daad743d8190383219f757dd66c
74 changes: 73 additions & 1 deletion trunk/drivers/xen/events.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ enum xen_irq_type {
*/
struct irq_info {
struct list_head list;
int refcnt;
enum xen_irq_type type; /* type */
unsigned irq;
unsigned short evtchn; /* event channel */
Expand Down Expand Up @@ -406,6 +407,7 @@ static void xen_irq_init(unsigned irq)
panic("Unable to allocate metadata for IRQ%d\n", irq);

info->type = IRQT_UNBOUND;
info->refcnt = -1;

irq_set_handler_data(irq, info);

Expand Down Expand Up @@ -469,6 +471,8 @@ static void xen_free_irq(unsigned irq)

irq_set_handler_data(irq, NULL);

WARN_ON(info->refcnt > 0);

kfree(info);

/* Legacy IRQ descriptors are managed by the arch. */
Expand Down Expand Up @@ -637,7 +641,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
if (irq != -1) {
printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n",
irq, gsi);
goto out; /* XXX need refcount? */
goto out;
}

irq = xen_allocate_irq_gsi(gsi);
Expand Down Expand Up @@ -939,9 +943,16 @@ static void unbind_from_irq(unsigned int irq)
{
struct evtchn_close close;
int evtchn = evtchn_from_irq(irq);
struct irq_info *info = irq_get_handler_data(irq);

mutex_lock(&irq_mapping_update_lock);

if (info->refcnt > 0) {
info->refcnt--;
if (info->refcnt != 0)
goto done;
}

if (VALID_EVTCHN(evtchn)) {
close.port = evtchn;
if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
Expand Down Expand Up @@ -970,6 +981,7 @@ static void unbind_from_irq(unsigned int irq)

xen_free_irq(irq);

done:
mutex_unlock(&irq_mapping_update_lock);
}

Expand Down Expand Up @@ -1065,6 +1077,66 @@ void unbind_from_irqhandler(unsigned int irq, void *dev_id)
}
EXPORT_SYMBOL_GPL(unbind_from_irqhandler);

int evtchn_make_refcounted(unsigned int evtchn)
{
int irq = evtchn_to_irq[evtchn];
struct irq_info *info;

if (irq == -1)
return -ENOENT;

info = irq_get_handler_data(irq);

if (!info)
return -ENOENT;

WARN_ON(info->refcnt != -1);

info->refcnt = 1;

return 0;
}
EXPORT_SYMBOL_GPL(evtchn_make_refcounted);

int evtchn_get(unsigned int evtchn)
{
int irq;
struct irq_info *info;
int err = -ENOENT;

mutex_lock(&irq_mapping_update_lock);

irq = evtchn_to_irq[evtchn];
if (irq == -1)
goto done;

info = irq_get_handler_data(irq);

if (!info)
goto done;

err = -EINVAL;
if (info->refcnt <= 0)
goto done;

info->refcnt++;
err = 0;
done:
mutex_unlock(&irq_mapping_update_lock);

return err;
}
EXPORT_SYMBOL_GPL(evtchn_get);

void evtchn_put(unsigned int evtchn)
{
int irq = evtchn_to_irq[evtchn];
if (WARN_ON(irq == -1))
return;
unbind_from_irq(irq);
}
EXPORT_SYMBOL_GPL(evtchn_put);

void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
{
int irq = per_cpu(ipi_to_irq, cpu)[vector];
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/xen/evtchn.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port)
rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, IRQF_DISABLED,
u->name, (void *)(unsigned long)port);
if (rc >= 0)
rc = 0;
rc = evtchn_make_refcounted(port);

return rc;
}
Expand Down
7 changes: 7 additions & 0 deletions trunk/include/xen/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
*/
void unbind_from_irqhandler(unsigned int irq, void *dev_id);

/*
* Allow extra references to event channels exposed to userspace by evtchn
*/
int evtchn_make_refcounted(unsigned int evtchn);
int evtchn_get(unsigned int evtchn);
void evtchn_put(unsigned int evtchn);

void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
int resend_irq_on_evtchn(unsigned int irq);
void rebind_evtchn_irq(int evtchn, int irq);
Expand Down

0 comments on commit e81426d

Please sign in to comment.