linux中断初始化

Load address: 0x91100000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
############################################
2.7 MiB/s
done
Bytes transferred = 21633572 (14a1a24 hex)
Using FM1@DTSEC6 device
TFTP from server 10.10.10.1; our IP address is 10.10.10.2
Filename ‘SFUQ.dtb’.
Load address: 0x92600000
Loading: ####
812.5 KiB/s
done
Bytes transferred = 52426 (ccca hex)

Booting kernel from Legacy Image at 90000000 …

Image Name: Linux-linux-4.19.x /nxp-ls1046ar
Image Type: AArch64 Linux Kernel Image (uncompressed)
Data Size: 17631744 Bytes = 16.8 MiB
Load Address: 80080000
Entry Point: 80080000
Verifying Checksum … OK

Loading init Ramdisk from Legacy Image at 91100000 …

Image Name: Linux-4.9.115-EMBSYS-CGEL-6.x
Image Type: AArch64 Linux RAMDisk Image (gzip compressed)
Data Size: 21633508 Bytes = 20.6 MiB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum … OK

Flattened Device Tree blob at 92600000

Booting using the fdt blob at 0x92600000
Loading Kernel Image … OK
reserving fdt memory region: addr=8ff000000 size=800000
reserving fdt memory region: addr=8f7000000 size=4000000
reserving fdt memory region: addr=ffe00000 size=200000
reserving fdt memory region: addr=af200000 size=200000
reserving fdt memory region: addr=af400000 size=100000
reserving fdt memory region: addr=affe0000 size=20000
reserving fdt memory region: addr=b0000000 size=200000
Using Device Tree in place at 0000000092600000, end 000000009261fcc9
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
fdt_update_ethernet_dt: Invalid SerDes prtcl 0x2333 for LS1046ARDB
WARNING: SEC firmware not running, no kaslr-seed

Starting kernel …

[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd082]
[ 0.000000] Linux version 4.19.82-rt30-CGEL-V6.02.10.R5.B2 (zhanged@62a5eb9b140c) (gcc version 6.2.0 (ZTE Embsys-TSP V4.0)) #2 SMP PREEMPT Mon Dec 30 18:33:59 CST 2019
[ 0.000000] Machine model: LS1046A RDB Board
[ 0.000000] Memory limited to 8126MB
[ 0.000000] efi: Getting EFI parameters from FDT:
[ 0.000000] efi: UEFI not found.
[ 0.000000] OF: reserved mem: initialized node qman-fqd, compatible id fsl,qman-fqd
[ 0.000000] OF: reserved mem: initialized node qman-pfdr, compatible id fsl,qman-pfdr
[ 0.000000] OF: reserved mem: initialized node bman-fbpr, compatible id fsl,bman-fbpr
[ 0.000000] cma: Reserved 32 MiB at 0x00000000f9c00000
[ 0.000000] random: get_random_bytes called from start_kernel+0xb8/0x488 with crng_init=0
[ 0.000000] percpu: Embedded 25 pages/cpu s62424 r8192 d31784 u102400
[ 0.000000] Detected PIPT I-cache on CPU0
[ 0.000000] ARM_SMCCC_ARCH_WORKAROUND_1 missing from firmware
[ 0.000000] CPU features: enabling workaround for EL2 vector hardening
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 2033376
[ 0.000000] Kernel command line: root=/dev/ram rw console=ttyS0,115200 mem=8126m isolcpus=7
[ 0.000000] Dentry cache hash table entries: 1048576 (order: 11, 8388608 bytes)
[ 0.000000] Inode-cache hash table entries: 524288 (order: 10, 4194304 bytes)
[ 0.000000] software IO TLB: mapped [mem 0xf5c00000-0xf9c00000] (64MB)
[ 0.000000] Memory: 7894288K/8263680K available (11004K kernel code, 1218K rwdata, 3712K rodata, 1216K init, 9129K bss, 336624K reserved, 32768K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[ 0.000000] ftrace: allocating 36775 entries in 144 pages
[ 0.000000] rcu: Preemptible hierarchical RCU implementation.
[ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=4.
[ 0.000000] Tasks RCU enabled.
[ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.19.82-rt30-CGEL-V6.02.10.R5.B2 #2
[ 0.000000] Hardware name: LS1046A RDB Board (DT)
[ 0.000000] Call trace:
[ 0.000000] dump_backtrace+0x0/0x1c0
[ 0.000000] show_stack+0x24/0x30
[ 0.000000] dump_stack+0xa4/0xcc
[ 0.000000] gic_of_init+0x48/0x400
[ 0.000000] of_irq_init+0x188/0x2fc
[ 0.000000] irqchip_init+0x1c/0x24
[ 0.000000] init_IRQ+0xe8/0x118
[ 0.000000] start_kernel+0x2fc/0x488
[ 0.000000] GIC: Adjusting CPU interface base to 0x000000000142f000
[ 0.000000] GIC: Using split EOI/Deactivate mode
[ 0.000000] error gic_cnt 1

在linux4.19内核中,不存在4.9内核中关于中断的修改,所以尝试复现出这个故障,现在已经复现这个故障。

  1. 50服务器linux目录下 ukpmake编译出uImage和usr_int.ko

  2. 用户态执行testapp,然后ubp_hal_irq_request(17, dummy1, 55, 0,0,“test1”)
    得到的错误打印如下:
    [BSP]ubp_hal_irq_request(17, dummy1, 55, 0,0,“test1”)
    [ 800.399230] irq: no irq domain found for !
    [ 800.404204] K error @ usr_int_connect:302 -
    [ 800.404206] request irq for 17 failed with ret -22
    [error]@[ BSP_IRQ_request 265]: connect to kernel for irq 17d failed!ret -1

    4294967275 , 0xffffffeb
    

具体的回溯信息:
[BSP]ubp_hal_irq_request(17, dummy1, 55, 0, 0, “test1”)

[ 146.647550] CPU: 0 PID: 2029 Comm: TESTAPP Tainted: G O 4.19.82-rt30-CGEL-V6.02.10.R5.B2 #3
[ 146.657209] Hardware name: LS1046A RDB Board (DT)
[ 146.661909] Call trace:
[ 146.664353] dump_backtrace+0x0/0x1c0
[ 146.668010] show_stack+0x24/0x30
[ 146.671324] dump_stack+0xa4/0xcc
[ 146.674635] irq_create_fwspec_mapping+0x1c4/0x348
[ 146.679428] usr_int_connect+0x360/0x610 [usr_int]
[ 146.684216] usr_int_ioctl+0x38c/0x698 [usr_int]
[ 146.688831] do_vfs_ioctl+0xc4/0x8a0
[ 146.692401] ksys_ioctl+0x8c/0xa0
[ 146.695710] __arm64_sys_ioctl+0x28/0x38
[ 146.699629] el0_svc_common.constprop.0+0xd0/0x178
[ 146.704416] el0_svc_handler+0x34/0x98
[ 146.708161] el0_svc+0x8/0xc
[ 146.711043] irq: no irq domain found for !
[ 146.716009] K error @ usr_int_connect:302 -
[ 146.716011] request irq for 17 failed with ret -22
[error]@[ BSP_IRQ_request 265]: connect to kernel for irq 17d failed!ret -1

4294967275 , 0xffffffeb

其中错误语句 irq: no irq domain found for ! 由函数irq_create_fwspec_mapping打印,所以在这一样里面加了打印,发现内核启动时有非常多的回溯打出来。

典型的回溯如下:
imx-i2c 2180000.i2c: scl-gpios not found
[ 8.765981] CPU: 1 PID: 91 Comm: kworker/1:1 Not tainted 4.19.82-rt30-CGEL-V6.02.10.R5.B2 #3
[ 8.774420] Hardware name: LS1046A RDB Board (DT)
[ 8.779125] Workqueue: events deferred_probe_work_func
[ 8.784261] Call trace:
[ 8.786702] dump_backtrace+0x0/0x1c0
[ 8.790359] show_stack+0x24/0x30
[ 8.793670] dump_stack+0xa4/0xcc
[ 8.796979] irq_create_fwspec_mapping+0x1c4/0x348
[ 8.801767] irq_create_of_mapping+0x7c/0xa8
[ 8.806034] of_irq_get+0xa0/0x110
[ 8.809430] platform_get_irq+0x2c/0x108
[ 8.813348] i2c_imx_probe+0x64/0x748
[ 8.817004] platform_drv_probe+0x58/0xb8
[ 8.821008] really_probe+0x218/0x2b8
[ 8.824665] driver_probe_device+0x60/0x108
[ 8.828843] __device_attach_driver+0x98/0xe8
[ 8.833196] bus_for_each_drv+0x80/0xe0
[ 8.837026] __device_attach+0xe8/0x148
[ 8.840857] device_initial_probe+0x24/0x30
[ 8.845036] bus_probe_device+0xa0/0xa8
[ 8.848866] deferred_probe_work_func+0x74/0xa8
[ 8.853393] process_one_work+0x224/0x4b0
[ 8.857397] worker_thread+0x254/0x438
[ 8.861141] kthread+0x104/0x130
[ 8.864364] ret_from_fork+0x10/0x18
[ 8.867999] imx-i2c 2180000.i2c: scl-gpios not found

[ 8.438019] Hardware name: LS1046A RDB Board (DT)
[ 8.442720] Call trace:
[ 8.445163] dump_backtrace+0x0/0x1c0
[ 8.448819] show_stack+0x24/0x30
[ 8.452133] dump_stack+0xa4/0xcc
[ 8.455444] irq_create_fwspec_mapping+0x1c4/0x348
[ 8.460231] irq_create_of_mapping+0x7c/0xa8
[ 8.464497] of_irq_get+0xa0/0x110
[ 8.467895] platform_get_irq+0x2c/0x108
[ 8.471815] sdhci_pltfm_init+0x64/0x158
[ 8.475733] sdhci_esdhc_probe+0x3cc/0x410
[ 8.479824] platform_drv_probe+0x58/0xb8
[ 8.483828] really_probe+0x218/0x2b8
[ 8.487484] driver_probe_device+0x60/0x108
[ 8.491661] __driver_attach+0x104/0x108
[ 8.495580] bus_for_each_dev+0x78/0xe0
[ 8.499410] driver_attach+0x30/0x40
[ 8.502979] bus_add_driver+0x110/0x230
[ 8.506810] driver_register+0x68/0x118
[ 8.510641] __platform_driver_register+0x54/0x60
[ 8.515343] sdhci_esdhc_driver_init+0x20/0x28
[ 8.519783] do_one_initcall+0x54/0x250
[ 8.523614] kernel_init_freeable+0x21c/0x384
[ 8.527967] kernel_init+0x18/0x110
[ 8.531449] ret_from_fork+0x10/0x18
[ 8.032733] dwc3 3100000.usb: Failed to get clk ‘ref’: -2

[ 8.038206] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.82-rt30-CGEL-V6.02.10.R5.B2 #3
[ 8.046384] Hardware name: LS1046A RDB Board (DT)
[ 8.051082] Call trace:
[ 8.053522] dump_backtrace+0x0/0x1c0
[ 8.057178] show_stack+0x24/0x30
[ 8.060488] dump_stack+0xa4/0xcc
[ 8.063798] irq_create_fwspec_mapping+0x1c4/0x348
[ 8.068585] irq_create_of_mapping+0x7c/0xa8
[ 8.072852] of_irq_get+0xa0/0x110
[ 8.076248] platform_get_irq+0x2c/0x108
[ 8.080166] dwc3_host_init+0x280/0x380
[ 8.083997] dwc3_probe+0xa1c/0xb28
[ 8.087480] platform_drv_probe+0x58/0xb8
[ 8.091484] really_probe+0x218/0x2b8
[ 8.095141] driver_probe_device+0x60/0x108
[ 8.099318] __driver_attach+0x104/0x108
[ 8.103237] bus_for_each_dev+0x78/0xe0
[ 8.107067] driver_attach+0x30/0x40
[ 8.110636] bus_add_driver+0x110/0x230
[ 8.114467] driver_register+0x68/0x118
[ 8.118297] __platform_driver_register+0x54/0x60
[ 8.122998] dwc3_driver_init+0x20/0x28
[ 8.126829] do_one_initcall+0x54/0x250
[ 8.130660] kernel_init_freeable+0x21c/0x384
[ 8.135012] kernel_init+0x18/0x110
[ 8.138495] ret_from_fork+0x10/0x18

由此可见,对于内核中的驱动而言,当通过platform_get_irq注册中断信息时,会为中断创建映射关系。

platform_get_irq 该函数的第一个参数是设备树节点,第二个参数通常是0.
of_irq_get(dev->dev.of_node, num);
of_irq_parse_one(dev, index, &oirq); 从设备树解析出中断
irq_find_host(oirq.np); 判断domain是否存在。
irq_create_of_mapping(&oirq);
of_phandle_args_to_fwspec(irq_data, &fwspec);
irq_create_fwspec_mapping(&fwspec); 我家的打印就位于这里。

platform_get_irq之后返回的是linux的虚拟中断号,之后驱动将会调用devm_request_irq对中断进行注册。 具体例子可见i2c的函数i2c_imx_probe。

unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
{
struct irq_domain *domain;
struct irq_data *irq_data;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
int virq;

if (fwspec->fwnode) {
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
printk(“error irq_create_fwspec_mapping domain is 11111111\n”);
if (!domain){
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_ANY);
printk(“error irq_create_fwspec_mapping domain is 22222222\n”);
}
} else {
printk(“error irq_create_fwspec_mapping domain is default\n”);
domain = irq_default_domain;
}

dump_stack();

if (!domain) {
pr_warn(“no irq domain found for %s !\n”,
of_node_full_name(to_of_node(fwspec->fwnode)));
return 0;
}

…………;
}

no irq domain found for 这句话的意思就是没有找到domain,其实也就是没有找到irq号所对应的控制器。那么往上看代码发现,
找domain的流程有if else的区分。再次加打印,发现内核中驱动注册时走的是 fwspec->fwnode流程,而当用户态通过中断框架调用时,走的是else流程,即domain = irq_default_domain; 回想起来4.9加了对irq_default_domain进行赋值的语句,可见问题出自于此。

再看周武的中断代码,用户态传进来的irq其实是硬件中断号,需要先进行映射才可以传给request_irq. 那么问题就出在周武的代码这里:

     if(pudesc->irq_mapped == -1)
          {
                #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
                    memset(&fwspec, 0, sizeof(fwspec));
                    fwspec.fwnode = NULL;            /*dts节点为空。下面的map函数流程根据这个改变走向*/
                    fwspec.param_count = 3;     
                    fwspec.param[0] = 0;            /* GIC type; data:0-GIC_SPI 1-GIC_PPI */
                    fwspec.param[1] = pudesc->irq;  /* hwirq number */
                    fwspec.param[2] = pudesc->flag; /* irq trigger type */
                    pudesc->irq_mapped = irq_create_fwspec_mapping(&fwspec);
                                            
                #else
                    /* PPC T series didn't define CONFIG_IRQ_DOMAIN_HIERARCHY */
                    pudesc->irq_mapped = irq_create_mapping(NULL, pudesc->irq);
                #endif  /* end CONFIG_IRQ_DOMAIN_HIERARCHY */
                
                    if(pudesc->irq_mapped < 0)
                    {
                        KUI_ERR("irq_create_mapping returned err with %d\n", pudesc->irq_mapped);
                        if(name)
                            kfree(name);
                        kfree(lpkdesc); 
                        pkdesc[id] = NULL;
                        return UI_ERROR_IRQ_MAP_FAILED;           
                    }
                    lpkdesc->udesc.irq_mapped = pudesc->irq_mapped;
          }
  ret = request_irq(pudesc->irq_mapped, usr_int_handler, irq_flag, name, lpkdesc);

解决办法:
1、of_irq_get_byname dts中配置,用户态传入时根据irq找到name,然后根据name找到domain。
2、用户态注册中断时,会传入name属性,可以在dts中加入节点,然后根据name找到这个dts节点,之后便可以注册成功。

内核驱动是如何注册中断的:
[ 8.796979] irq_create_fwspec_mapping+0x1c4/0x348
[ 8.801767] irq_create_of_mapping+0x7c/0xa8
[ 8.806034] of_irq_get+0xa0/0x91100000
[ 8.809430] platform_get_irq+0x2c/0x108 从dts中解析中断信息并将hwirq映射为virq。
[ 8.813348] i2c_imx_probe+0x64/0x748 i2c驱动初始化函数

只有会将platform_get_irq返回的virq作为入参,传给request_irq.

用户态注册时会打印一次如下的打印,经过咨询时正常的。内核在第一次时会打印,后面不在打印。
[BSP]ubp_hal_irq_request(17, dummy1, 55, 4, 0, “test1”)

connect to kerne[ 267.731233] WARNING: CPU: 0 PID: 2035 at /home/zhanged/linux/CGEL6.X/kernel/linux-4.19.x/kernel/irq/chip.c:242 __irq_startup+0xa0/0xa8
[ 267.744630] Modules linked in: usr_int(O)
[ 267.748641] CPU: 0 PID: 2035 Comm: test1 Tainted: G O 4.19.82-rt30-CGEL-V6.02.10.R5.B2 #24
[ 267.758208] Hardware name: LS1046A RDB Board (DT)
[ 267.762909] pstate: 60000085 (nZCv daIf -PAN -UAO)
[ 267.767697] pc : __irq_startup+0xa0/0xa8
[ 267.771614] lr : irq_startup+0x7c/0x140
[ 267.775444] sp : ffff000010ddbba0
[ 267.778752] x29: ffff000010ddbba0 x28: ffff800972240000
[ 267.784063] x27: 0000000000000000 x26: 0000000000000000
[ 267.789373] x25: 0000000056000000 x24: ffff800971faa750
[ 267.794684] x23: 0000000000000000 x22: 0000000000000001
[ 267.799994] x21: 0000000000000001 x20: ffff800972c43800
[ 267.805305] x19: ffff800972c43828 x18: 0000000000000000
[ 267.810615] x17: 0000000000000000 x16: 0000000000000000
[ 267.815926] x15: 0000000000000000 x14: 0000000000000000
[ 267.821236] x13: 0000000000000000 x12: 0000000000000040
[ 267.826547] x11: 0000000000000000 x10: ffff800973000270
[ 267.831857] x9 : 0000000000000000 x8 : ffff800973000248
[ 267.837167] x7 : ffff800972c43800 x6 : ffff800972c43800
[ 267.842478] x5 : ffff8009730002f8 x4 : ffff800972c43800
[ 267.847788] x3 : ffff800972c43800 x2 : 0000000000000001
[ 267.853098] x1 : 0000000000000001 x0 : 0000000003030004
[ 267.858409] Call trace:
[ 267.860849] __irq_startup+0xa0/0xa8
[ 267.864418] irq_startup+0x7c/0x140
[ 267.867901] __enable_irq+0x80/0x88
[ 267.871383] enable_irq+0x58/0xb0
[ 267.874697] usr_int_ioctl+0x844/0xd80 [usr_int]
[ 267.879312] do_vfs_ioctl+0xc4/0x8a0
[ 267.882881] ksys_ioctl+0x8c/0xa0
[ 267.886191] __arm64_sys_ioctl+0x28/0x38
[ 267.890109] el0_svc_common.constprop.0+0xd0/0x178
[ 267.894897] el0_svc_handler+0x34/0x98
[ 267.898640] el0_svc+0x8/0xc
[ 267.901514] —[ end trace 6b6b77d42e4289a7 ]—
l for irq 17d OK!irq mapped to 77, id assigned to 0
create usr int thread for int_id 0 OK, pri 55, ntid 0xffffb38e80a0

看门狗问题优化方案:
drivers/watchdog/gpio_wdt.c

  static struct platform_driver gpio_wdt_driver = {
  .driver  = {
     .name    = "gpio-wdt",
     .of_match_table   = gpio_wdt_dt_ids,
  },
  .probe   = gpio_wdt_probe,
  .remove  = gpio_wdt_remove,
  };

  #ifdef CONFIG_GPIO_WATCHDOG_ARCH_INITCALL
  static int __init gpio_wdt_init(void)
  {
     return platform_driver_register(&gpio_wdt_driver);
  }
  arch_initcall(gpio_wdt_init);
  #else
  module_platform_driver(gpio_wdt_driver);
  #endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值