[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 08/13] xen/events: allow setup of irq_info to fail



On Fri, Sep 13, 2013 at 05:59:56PM +0100, David Vrabel wrote:
> From: David Vrabel <david.vrabel@xxxxxxxxxx>
> 
> The FIFO-based event ABI requires additional setup of newly bound
> events (it may need to expand the event array) and this setup may
> fail.
> 
> xen_irq_info_common_init() is a useful place to put this setup so
> allow this call to fail.  This call and the other similar calls are
> renamed to be *_setup() to reflect that they may now fail.
> 
> This failure can only occur with new event channels not on rebind.


Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>


> 
> Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
> ---
>  drivers/xen/events/events.c |  156 
> +++++++++++++++++++++++++------------------
>  1 files changed, 91 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/xen/events/events.c b/drivers/xen/events/events.c
> index 8ecde63..8f55a49 100644
> --- a/drivers/xen/events/events.c
> +++ b/drivers/xen/events/events.c
> @@ -99,7 +99,7 @@ struct irq_info *info_for_irq(unsigned irq)
>  }
>  
>  /* Constructors for packed IRQ information. */
> -static void xen_irq_info_common_init(struct irq_info *info,
> +static int xen_irq_info_common_setup(struct irq_info *info,
>                                    unsigned irq,
>                                    enum xen_irq_type type,
>                                    unsigned short evtchn,
> @@ -116,45 +116,47 @@ static void xen_irq_info_common_init(struct irq_info 
> *info,
>       evtchn_to_irq[evtchn] = irq;
>  
>       irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN);
> +
> +     return 0;
>  }
>  
> -static void xen_irq_info_evtchn_init(unsigned irq,
> +static int xen_irq_info_evtchn_setup(unsigned irq,
>                                    unsigned short evtchn)
>  {
>       struct irq_info *info = info_for_irq(irq);
>  
> -     xen_irq_info_common_init(info, irq, IRQT_EVTCHN, evtchn, 0);
> +     return xen_irq_info_common_setup(info, irq, IRQT_EVTCHN, evtchn, 0);
>  }
>  
> -static void xen_irq_info_ipi_init(unsigned cpu,
> +static int xen_irq_info_ipi_setup(unsigned cpu,
>                                 unsigned irq,
>                                 unsigned short evtchn,
>                                 enum ipi_vector ipi)
>  {
>       struct irq_info *info = info_for_irq(irq);
>  
> -     xen_irq_info_common_init(info, irq, IRQT_IPI, evtchn, 0);
> -
>       info->u.ipi = ipi;
>  
>       per_cpu(ipi_to_irq, cpu)[ipi] = irq;
> +
> +     return xen_irq_info_common_setup(info, irq, IRQT_IPI, evtchn, 0);
>  }
>  
> -static void xen_irq_info_virq_init(unsigned cpu,
> +static int xen_irq_info_virq_setup(unsigned cpu,
>                                  unsigned irq,
>                                  unsigned short evtchn,
>                                  unsigned short virq)
>  {
>       struct irq_info *info = info_for_irq(irq);
>  
> -     xen_irq_info_common_init(info, irq, IRQT_VIRQ, evtchn, 0);
> -
>       info->u.virq = virq;
>  
>       per_cpu(virq_to_irq, cpu)[virq] = irq;
> +
> +     return xen_irq_info_common_setup(info, irq, IRQT_VIRQ, evtchn, 0);
>  }
>  
> -static void xen_irq_info_pirq_init(unsigned irq,
> +static int xen_irq_info_pirq_setup(unsigned irq,
>                                  unsigned short evtchn,
>                                  unsigned short pirq,
>                                  unsigned short gsi,
> @@ -163,12 +165,12 @@ static void xen_irq_info_pirq_init(unsigned irq,
>  {
>       struct irq_info *info = info_for_irq(irq);
>  
> -     xen_irq_info_common_init(info, irq, IRQT_PIRQ, evtchn, 0);
> -
>       info->u.pirq.pirq = pirq;
>       info->u.pirq.gsi = gsi;
>       info->u.pirq.domid = domid;
>       info->u.pirq.flags = flags;
> +
> +     return xen_irq_info_common_setup(info, irq, IRQT_PIRQ, evtchn, 0);
>  }
>  
>  /*
> @@ -516,6 +518,47 @@ int xen_irq_from_gsi(unsigned gsi)
>  }
>  EXPORT_SYMBOL_GPL(xen_irq_from_gsi);
>  
> +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);
> +
> +     if (info->refcnt > 0) {
> +             info->refcnt--;
> +             if (info->refcnt != 0)
> +                     return;
> +     }
> +
> +     if (VALID_EVTCHN(evtchn)) {
> +             close.port = evtchn;
> +             if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
> +                     BUG();
> +
> +             switch (type_from_irq(irq)) {
> +             case IRQT_VIRQ:
> +                     per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
> +                             [virq_from_irq(irq)] = -1;
> +                     break;
> +             case IRQT_IPI:
> +                     per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
> +                             [ipi_from_irq(irq)] = -1;
> +                     break;
> +             default:
> +                     break;
> +             }
> +
> +             /* Closed ports are implicitly re-bound to VCPU0. */
> +             bind_evtchn_to_cpu(evtchn, 0);
> +
> +             evtchn_to_irq[evtchn] = -1;
> +     }
> +
> +     BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND);
> +
> +     xen_free_irq(irq);
> +}
> +
>  /*
>   * Do not make any assumptions regarding the relationship between the
>   * IRQ number returned here and the Xen pirq argument.
> @@ -531,6 +574,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
>  {
>       int irq = -1;
>       struct physdev_irq irq_op;
> +     int ret;
>  
>       mutex_lock(&irq_mapping_update_lock);
>  
> @@ -558,8 +602,13 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
>               goto out;
>       }
>  
> -     xen_irq_info_pirq_init(irq, 0, pirq, gsi, DOMID_SELF,
> +     ret = xen_irq_info_pirq_setup(irq, 0, pirq, gsi, DOMID_SELF,
>                              shareable ? PIRQ_SHAREABLE : 0);
> +     if (ret < 0) {
> +             __unbind_from_irq(irq);
> +             irq = ret;
> +             goto out;
> +     }
>  
>       pirq_query_unmask(irq);
>       /* We try to use the handler with the appropriate semantic for the
> @@ -619,7 +668,9 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct 
> msi_desc *msidesc,
>       irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
>                       name);
>  
> -     xen_irq_info_pirq_init(irq, 0, pirq, 0, domid, 0);
> +     ret = xen_irq_info_pirq_setup(irq, 0, pirq, 0, domid, 0);
> +     if (ret < 0)
> +             goto error_irq;
>       ret = irq_set_msi_desc(irq, msidesc);
>       if (ret < 0)
>               goto error_irq;
> @@ -627,8 +678,8 @@ out:
>       mutex_unlock(&irq_mapping_update_lock);
>       return irq;
>  error_irq:
> +     __unbind_from_irq(irq);
>       mutex_unlock(&irq_mapping_update_lock);
> -     xen_free_irq(irq);
>       return ret;
>  }
>  #endif
> @@ -698,9 +749,11 @@ int xen_pirq_from_irq(unsigned irq)
>       return pirq_from_irq(irq);
>  }
>  EXPORT_SYMBOL_GPL(xen_pirq_from_irq);
> +
>  int bind_evtchn_to_irq(unsigned int evtchn)
>  {
>       int irq;
> +     int ret;
>  
>       mutex_lock(&irq_mapping_update_lock);
>  
> @@ -714,7 +767,12 @@ int bind_evtchn_to_irq(unsigned int evtchn)
>               irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
>                                             handle_edge_irq, "event");
>  
> -             xen_irq_info_evtchn_init(irq, evtchn);
> +             ret = xen_irq_info_evtchn_setup(irq, evtchn);
> +             if (ret < 0) {
> +                     __unbind_from_irq(irq);
> +                     irq = ret;
> +                     goto out;
> +             }
>       } else {
>               struct irq_info *info = info_for_irq(irq);
>               WARN_ON(info == NULL || info->type != IRQT_EVTCHN);
> @@ -731,6 +789,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int 
> cpu)
>  {
>       struct evtchn_bind_ipi bind_ipi;
>       int evtchn, irq;
> +     int ret;
>  
>       mutex_lock(&irq_mapping_update_lock);
>  
> @@ -750,8 +809,12 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned 
> int cpu)
>                       BUG();
>               evtchn = bind_ipi.port;
>  
> -             xen_irq_info_ipi_init(cpu, irq, evtchn, ipi);
> -
> +             ret = xen_irq_info_ipi_setup(cpu, irq, evtchn, ipi);
> +             if (ret < 0) {
> +                     __unbind_from_irq(irq);
> +                     irq = ret;
> +                     goto out;
> +             }
>               bind_evtchn_to_cpu(evtchn, cpu);
>       } else {
>               struct irq_info *info = info_for_irq(irq);
> @@ -830,7 +893,12 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
>                       evtchn = ret;
>               }
>  
> -             xen_irq_info_virq_init(cpu, irq, evtchn, virq);
> +             ret = xen_irq_info_virq_setup(cpu, irq, evtchn, virq);
> +             if (ret < 0) {
> +                     __unbind_from_irq(irq);
> +                     irq = ret;
> +                     goto out;
> +             }
>  
>               bind_evtchn_to_cpu(evtchn, cpu);
>       } else {
> @@ -846,50 +914,8 @@ out:
>  
>  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);
> -
> -     if (WARN_ON(!info))
> -             return;
> -
>       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)
> -                     BUG();
> -
> -             switch (type_from_irq(irq)) {
> -             case IRQT_VIRQ:
> -                     per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
> -                             [virq_from_irq(irq)] = -1;
> -                     break;
> -             case IRQT_IPI:
> -                     per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
> -                             [ipi_from_irq(irq)] = -1;
> -                     break;
> -             default:
> -                     break;
> -             }
> -
> -             /* Closed ports are implicitly re-bound to VCPU0. */
> -             bind_evtchn_to_cpu(evtchn, 0);
> -
> -             evtchn_to_irq[evtchn] = -1;
> -     }
> -
> -     BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND);
> -
> -     xen_free_irq(irq);
> -
> - done:
> +     __unbind_from_irq(irq);
>       mutex_unlock(&irq_mapping_update_lock);
>  }
>  
> @@ -1137,7 +1163,7 @@ void rebind_evtchn_irq(int evtchn, int irq)
>          so there should be a proper type */
>       BUG_ON(info->type == IRQT_UNBOUND);
>  
> -     xen_irq_info_evtchn_init(irq, evtchn);
> +     xen_irq_info_evtchn_setup(irq, evtchn);
>  
>       mutex_unlock(&irq_mapping_update_lock);
>  
> @@ -1312,7 +1338,7 @@ static void restore_cpu_virqs(unsigned int cpu)
>               evtchn = bind_virq.port;
>  
>               /* Record the new mapping. */
> -             xen_irq_info_virq_init(cpu, irq, evtchn, virq);
> +             xen_irq_info_virq_setup(cpu, irq, evtchn, virq);
>               bind_evtchn_to_cpu(evtchn, cpu);
>       }
>  }
> @@ -1336,7 +1362,7 @@ static void restore_cpu_ipis(unsigned int cpu)
>               evtchn = bind_ipi.port;
>  
>               /* Record the new mapping. */
> -             xen_irq_info_ipi_init(cpu, irq, evtchn, ipi);
> +             xen_irq_info_ipi_setup(cpu, irq, evtchn, ipi);
>               bind_evtchn_to_cpu(evtchn, cpu);
>       }
>  }
> -- 
> 1.7.2.5
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.