[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 02/24] xen/arm: Divide GIC initialization in 2 parts
On Tue, 13 Jan 2015, Julien Grall wrote: > Currently the function to translate IRQ from the device tree is set > unconditionally to be able to be able to retrieve serial/timer IRQ before the > GIC has been initialized. > > It assumes that the xlate function won't never changed. We may also need to > have the primary interrupt controller very early. > > Rework the gic initialization in 2 parts: > - gic_preinit: Get the interrupt controller device tree node and set > up GIC and xlate callbacks > - gic_init: Initialize the interrupt controller and the boot CPU > interrupts. > > The former function will be called just after the IRQ subsystem as been > initialized. > > Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> > --- > Changes in v3: > - Patch was previously sent in a separate series [1] > - Reorder the function to avoid forward declaration > - Make gic-v3 driver compliant to the new interface > - Remove spurious field addition in gicv2 structure > > Changelog based on the separate series: > > Changes in v3: > - Patch added. > > [1] https://patches.linaro.org/33313/ > --- > xen/arch/arm/gic-v2.c | 70 ++++++++++++++++++++++--------------------- > xen/arch/arm/gic-v3.c | 75 > ++++++++++++++++++++++++----------------------- > xen/arch/arm/gic.c | 16 ++++++++-- > xen/arch/arm/setup.c | 3 +- > xen/include/asm-arm/gic.h | 8 +++++ > 5 files changed, 100 insertions(+), 72 deletions(-) > > diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c > index 15916c9..016b0fd 100644 > --- a/xen/arch/arm/gic-v2.c > +++ b/xen/arch/arm/gic-v2.c > @@ -655,37 +655,10 @@ static hw_irq_controller gicv2_guest_irq_type = { > .set_affinity = gicv2_irq_set_affinity, > }; > > -const static struct gic_hw_operations gicv2_ops = { > - .info = &gicv2_info, > - .secondary_init = gicv2_secondary_cpu_init, > - .save_state = gicv2_save_state, > - .restore_state = gicv2_restore_state, > - .dump_state = gicv2_dump_state, > - .gicv_setup = gicv2v_setup, > - .gic_host_irq_type = &gicv2_host_irq_type, > - .gic_guest_irq_type = &gicv2_guest_irq_type, > - .eoi_irq = gicv2_eoi_irq, > - .deactivate_irq = gicv2_dir_irq, > - .read_irq = gicv2_read_irq, > - .set_irq_properties = gicv2_set_irq_properties, > - .send_SGI = gicv2_send_SGI, > - .disable_interface = gicv2_disable_interface, > - .update_lr = gicv2_update_lr, > - .update_hcr_status = gicv2_hcr_status, > - .clear_lr = gicv2_clear_lr, > - .read_lr = gicv2_read_lr, > - .write_lr = gicv2_write_lr, > - .read_vmcr_priority = gicv2_read_vmcr_priority, > - .read_apr = gicv2_read_apr, > - .make_dt_node = gicv2_make_dt_node, > -}; > - > -/* Set up the GIC */ > -static int __init gicv2_init(struct dt_device_node *node, const void *data) > +static int __init gicv2_init(void) > { > int res; > - > - dt_device_set_used_by(node, DOMID_XEN); > + const struct dt_device_node *node = gicv2_info.node; > > res = dt_device_get_address(node, 0, &gicv2.dbase, NULL); > if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) ) > @@ -708,9 +681,6 @@ static int __init gicv2_init(struct dt_device_node *node, > const void *data) > panic("GICv2: Cannot find the maintenance IRQ"); > gicv2_info.maintenance_irq = res; > > - /* Set the GIC as the primary interrupt controller */ > - dt_interrupt_controller = node; > - > /* TODO: Add check on distributor, cpu size */ > > printk("GICv2 initialization:\n" > @@ -755,8 +725,42 @@ static int __init gicv2_init(struct dt_device_node > *node, const void *data) > > spin_unlock(&gicv2.lock); > > + return 0; > +} > + > +const static struct gic_hw_operations gicv2_ops = { > + .info = &gicv2_info, > + .init = gicv2_init, > + .secondary_init = gicv2_secondary_cpu_init, > + .save_state = gicv2_save_state, > + .restore_state = gicv2_restore_state, > + .dump_state = gicv2_dump_state, > + .gicv_setup = gicv2v_setup, > + .gic_host_irq_type = &gicv2_host_irq_type, > + .gic_guest_irq_type = &gicv2_guest_irq_type, > + .eoi_irq = gicv2_eoi_irq, > + .deactivate_irq = gicv2_dir_irq, > + .read_irq = gicv2_read_irq, > + .set_irq_properties = gicv2_set_irq_properties, > + .send_SGI = gicv2_send_SGI, > + .disable_interface = gicv2_disable_interface, > + .update_lr = gicv2_update_lr, > + .update_hcr_status = gicv2_hcr_status, > + .clear_lr = gicv2_clear_lr, > + .read_lr = gicv2_read_lr, > + .write_lr = gicv2_write_lr, > + .read_vmcr_priority = gicv2_read_vmcr_priority, > + .read_apr = gicv2_read_apr, > + .make_dt_node = gicv2_make_dt_node, > +}; > + > +/* Set up the GIC */ > +static int __init gicv2_preinit(struct dt_device_node *node, const void > *data) > +{ > gicv2_info.hw_version = GIC_V2; > + gicv2_info.node = node; > register_gic_ops(&gicv2_ops); > + dt_irq_xlate = gic_irq_xlate; > > return 0; > } > @@ -769,7 +773,7 @@ static const struct dt_device_match gicv2_dt_match[] > __initconst = > > DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC) > .dt_match = gicv2_dt_match, > - .init = gicv2_init, > + .init = gicv2_preinit, > DT_DEVICE_END > > /* > diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c > index 2ddcbab..f650756 100644 > --- a/xen/arch/arm/gic-v3.c > +++ b/xen/arch/arm/gic-v3.c > @@ -1141,37 +1141,13 @@ static const hw_irq_controller gicv3_guest_irq_type = > { > .set_affinity = gicv3_irq_set_affinity, > }; > > -static const struct gic_hw_operations gicv3_ops = { > - .info = &gicv3_info, > - .save_state = gicv3_save_state, > - .restore_state = gicv3_restore_state, > - .dump_state = gicv3_dump_state, > - .gicv_setup = gicv_v3_init, > - .gic_host_irq_type = &gicv3_host_irq_type, > - .gic_guest_irq_type = &gicv3_guest_irq_type, > - .eoi_irq = gicv3_eoi_irq, > - .deactivate_irq = gicv3_dir_irq, > - .read_irq = gicv3_read_irq, > - .set_irq_properties = gicv3_set_irq_properties, > - .send_SGI = gicv3_send_sgi, > - .disable_interface = gicv3_disable_interface, > - .update_lr = gicv3_update_lr, > - .update_hcr_status = gicv3_hcr_status, > - .clear_lr = gicv3_clear_lr, > - .read_lr = gicv3_read_lr, > - .write_lr = gicv3_write_lr, > - .read_vmcr_priority = gicv3_read_vmcr_priority, > - .read_apr = gicv3_read_apr, > - .secondary_init = gicv3_secondary_cpu_init, > - .make_dt_node = gicv3_make_dt_node, > -}; > - > /* Set up the GIC */ > -static int __init gicv3_init(struct dt_device_node *node, const void *data) > +static int __init gicv3_init(void) > { > struct rdist_region *rdist_regs; > int res, i; > uint32_t reg; > + const struct dt_device_node *node = gicv3_info.node; > > if ( !cpu_has_gicv3 ) > { > @@ -1179,8 +1155,6 @@ static int __init gicv3_init(struct dt_device_node > *node, const void *data) > return -ENODEV; > } > > - dt_device_set_used_by(node, DOMID_XEN); > - > res = dt_device_get_address(node, 0, &gicv3.dbase, &gicv3.dbase_size); > if ( res || !gicv3.dbase ) > panic("GICv3: Cannot find a valid distributor address"); > @@ -1232,9 +1206,6 @@ static int __init gicv3_init(struct dt_device_node > *node, const void *data) > panic("GICv3: Cannot find the maintenance IRQ"); > gicv3_info.maintenance_irq = res; > > - /* Set the GIC as the primary interrupt controller */ > - dt_interrupt_controller = node; > - > for ( i = 0; i < gicv3.rdist_count; i++ ) > { > /* map dbase & rdist regions */ > @@ -1269,15 +1240,47 @@ static int __init gicv3_init(struct dt_device_node > *node, const void *data) > res = gicv3_cpu_init(); > gicv3_hyp_init(); > > - gicv3_info.hw_version = GIC_V3; > - /* Register hw ops*/ > - register_gic_ops(&gicv3_ops); > - > spin_unlock(&gicv3.lock); > > return res; > } > > +static const struct gic_hw_operations gicv3_ops = { > + .info = &gicv3_info, > + .init = gicv3_init, > + .save_state = gicv3_save_state, > + .restore_state = gicv3_restore_state, > + .dump_state = gicv3_dump_state, > + .gicv_setup = gicv_v3_init, > + .gic_host_irq_type = &gicv3_host_irq_type, > + .gic_guest_irq_type = &gicv3_guest_irq_type, > + .eoi_irq = gicv3_eoi_irq, > + .deactivate_irq = gicv3_dir_irq, > + .read_irq = gicv3_read_irq, > + .set_irq_properties = gicv3_set_irq_properties, > + .send_SGI = gicv3_send_sgi, > + .disable_interface = gicv3_disable_interface, > + .update_lr = gicv3_update_lr, > + .update_hcr_status = gicv3_hcr_status, > + .clear_lr = gicv3_clear_lr, > + .read_lr = gicv3_read_lr, > + .write_lr = gicv3_write_lr, > + .read_vmcr_priority = gicv3_read_vmcr_priority, > + .read_apr = gicv3_read_apr, > + .secondary_init = gicv3_secondary_cpu_init, > + .make_dt_node = gicv3_make_dt_node, > +}; > + > +static int __init gicv3_preinit(struct dt_device_node *node, const void > *data) > +{ > + gicv3_info.hw_version = GIC_V3; > + gicv3_info.node = node; > + register_gic_ops(&gicv3_ops); > + dt_irq_xlate = gic_irq_xlate; > + > + return 0; > +} > + > static const struct dt_device_match gicv3_dt_match[] __initconst = > { > DT_MATCH_GIC_V3, > @@ -1286,7 +1289,7 @@ static const struct dt_device_match gicv3_dt_match[] > __initconst = > > DT_DEVICE_START(gicv3, "GICv3", DEVICE_GIC) > .dt_match = gicv3_dt_match, > - .init = gicv3_init, > + .init = gicv3_preinit, > DT_DEVICE_END > > /* > diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c > index d1ab6b5..63147f3 100644 > --- a/xen/arch/arm/gic.c > +++ b/xen/arch/arm/gic.c > @@ -163,8 +163,10 @@ int gic_irq_xlate(const u32 *intspec, unsigned int > intsize, > return 0; > } > > -/* Set up the GIC */ > -void __init gic_init(void) > +/* Find the interrupt controller and set up the callback to translate > + * device tree IRQ. > + */ > +void __init gic_preinit(void) > { > int rc; > struct dt_device_node *node; > @@ -189,6 +191,16 @@ void __init gic_init(void) > if ( !num_gics ) > panic("Unable to find compatible GIC in the device tree"); > > + /* Set the GIC as the primary interrupt controller */ > + dt_interrupt_controller = node; > + dt_device_set_used_by(node, DOMID_XEN); > +} > + > +/* Set up the GIC */ > +void __init gic_init(void) > +{ > + if ( gic_hw_ops->init() ) > + panic("Failed to initialize the GIC drivers"); > /* Clear LR mask for cpu0 */ > clear_cpu_lr_mask(); > } > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c > index 4d242e0..18227f6 100644 > --- a/xen/arch/arm/setup.c > +++ b/xen/arch/arm/setup.c > @@ -740,10 +740,11 @@ void __init start_xen(unsigned long boot_phys_offset, > > vm_init(); > dt_unflatten_host_device_tree(); > - dt_irq_xlate = gic_irq_xlate; > > init_IRQ(); > > + gic_preinit(); > + > dt_uart_init(); > console_init_preirq(); > console_init_ring(); > diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h > index 73ca3cf..6286c71 100644 > --- a/xen/include/asm-arm/gic.h > +++ b/xen/include/asm-arm/gic.h > @@ -229,6 +229,10 @@ extern void gic_remove_from_queues(struct vcpu *v, > unsigned int virtual_irq); > > /* Accept an interrupt from the GIC and dispatch its handler */ > extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq); > +/* Find the interrupt controller and set up the callback to translate > + * device tree IRQ. > + */ > +extern void gic_preinit(void); > /* Bring up the interrupt controller, and report # cpus attached */ > extern void gic_init(void); > /* Bring up a secondary CPU's per-CPU GIC interface */ > @@ -281,11 +285,15 @@ struct gic_info { > uint8_t nr_lrs; > /* Maintenance irq number */ > unsigned int maintenance_irq; > + /* Pointer to the device tree node representing the interrupt controller > */ > + const struct dt_device_node *node; > }; > > struct gic_hw_operations { > /* Hold GIC HW information */ > const struct gic_info *info; > + /* Initialize the GIC and the boot CPU */ > + int (*init)(void); > /* Save GIC registers */ > void (*save_state)(struct vcpu *); > /* Restore GIC registers */ > -- > 2.1.4 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |