中断设置cpu亲和性代码编写

Linux中描述中断控制器的数据结构是struct irq_chip,因为不同芯片的中断控制器对其挂接的IRQ有不同的控制方法,因而这个结构体主要是由一组用于回调(callback),指向系统实际的中断控制器所使用的控制方法的函数指针构成。

struct irq_chip {
  const char      *name;
  unsigned int    (*irq_startup)(struct irq_data *data);
  void (*irq_shutdown)(struct irq_data *data);
  void (*irq_enable)(struct irq_data *data);
  void (*irq_disable)(struct irq_data *data);
  void (*irq_ack)(struct irq_data *data);
  void (*irq_mask)(struct irq_data *data);
  void (*irq_mask_ack)(struct irq_data *data);
  void (*irq_unmask)(struct irq_data *data);
  void (*irq_eoi)(struct irq_data *data);
  int (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
  int (*irq_retrigger)(struct irq_data *data);
  int (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
  int (*irq_set_wake)(struct irq_data *data, unsigned int on);
  void (*irq_bus_lock)(struct irq_data *data);
  void (*irq_bus_sync_unlock)(struct irq_data *data);
#ifdef CONFIG_DEPRECATED_IRQ_CPU_ONOFFLINE;
  void (*irq_cpu_online)(struct irq_data *data);
  void (*irq_cpu_offline)(struct irq_data *data);
#endif;
  void (*irq_suspend)(struct irq_data *data);
  void (*irq_resume)(struct irq_data *data);
  void (*irq_pm_shutdown)(struct irq_data *data);
  void (*irq_calc_mask)(struct irq_data *data);
  void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
  int (*irq_request_resources)(struct irq_data *data);
  void (*irq_release_resources)(struct irq_data *data);
  void (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg);
  void (*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);
  int (*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state);
  int (*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);
  int (*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
  void (*ipi_send_single)(struct irq_data *data, unsigned int cpu);
  void (*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);
  int (*irq_nmi_setup)(struct irq_data *data);
  void (*irq_nmi_teardown)(struct irq_data *data);
  unsigned long   flags;
};

在设备树中对应的节点添加中断相关的内容

        gpio0: gpio@e6050000 {
            compatible = "renesas,gpio-r8a7796",
                     "renesas,rcar-gen3-gpio";
            reg = <0 0xe6050000 0 0x50>;
        +    interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
        +    #gpio-cells = <2>;
            gpio-controller;
            gpio-ranges = <&pfc 0 0 16>;
        +    #interrupt-cells = <2>;
        +    interrupt-controller;
            clocks = <&cpg CPG_MOD 912>;
            power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
            resets = <&cpg 912>;
        };

 

正常驱动的中断实现,我们在驱动代码中实现struc irq_chip结构体的回调函数即可

static struct irq_chip ***_gpio_irqchip = {
        .name                   = "***_gpio",
        .irq_ack                = ***_gpio_irq_ack,
        .irq_set_type           = ***_gpio_irq_set_type,
        .irq_enable             = ***_gpio_irq_enable,
        .irq_disable            = ***_gpio_irq_disable,
       .irq_set_affinity       = ***_gpio_set_affinity,
 }; 

现因为要设置中断亲和性代码,即要中断绑定cpu的代码,我们实现 .irq_set_affinity这个回调函数即可

int ***_gpio_set_affinity(struct irq_data *d,
                                const struct cpumask *mask_val, bool force)
{
        struct gpio_chip *chip_data=irq_data_get_irq_chip_data(d);
        struct irq_chip *chip =irq_get_chip(chip_data->irq.parent_irq);
        struct irq_data *data = irq_get_irq_data(chip_data->irq.parent_irq);

        printk(KERN_ALERT"parent_irq:%d\n", chip_data->irq.parent_irq);
        if (chip && chip->irq_set_affinity){
                printk(KERN_ALERT"force:%d\n", force);
                return chip->irq_set_affinity(data, mask_val, force);
        }
        else {
                return -EINVAL;
        }
}

 

posted @ 2022-09-20 10:27  蒲城小农  阅读(380)  评论(0编辑  收藏  举报