海思Hi3559AV100的中断IRQ的处理器Affinity设置问题

      由前篇文章《海思Hi3559AV100平台韦根接收程序 》引出了一个问题,本应该写在那篇文章中,但由于内容较多,且属于相对独立的一块,所以专门开一篇文章详细说明。

      之前发现在海思平台上运行韦根接收程序时,会产生丢中断的现象,当时分析是由于海思芯片中运行了很多MPP模块,这些模块影响了韦根接收程序中用到的GPIO外部中断。

      进一步分析印证了当时的判断,根据运行cat /proc/interrupts命令得到的结果发现(见下面),绝大多数中断都在CPU0上,韦根所用的中断也分配到了CPU0上,这就会产生上述问题。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

           CPU0       CPU1       CPU2       CPU3       
  1:          0          0          0          0     GIC-0  29 Level     arch_timer
  2:    9156822    9156735    9156532    9156650     GIC-0  30 Level     arch_timer
  3:          0          0          0          0     GIC-0 243 Level     ipcm
  9:        157          0          0          0     GIC-0  38 Level     uart-pl011
 14:          0          0          0          0     GIC-0  63 Level     pl022
 15:          0          0          0          0     GIC-0  64 Level     pl022
 16:          0          0          0          0     GIC-0  65 Level     pl022
 17:          0          0          0          0     GIC-0  66 Level     pl022
 18:          0          0          0          0     GIC-0  67 Level     pl022
 19:          0          0          0          0     GIC-0 192 Level     12140000.gpio_chip
 20:          0          0          0          0     GIC-0 193 Level     12141000.gpio_chip
 21:          0          0          0          0     GIC-0 194 Level     12142000.gpio_chip
 22:          0          0          0          0     GIC-0 195 Level     12143000.gpio_chip
 23:          0          0          0          0     GIC-0 196 Level     12144000.gpio_chip
 24:          0          0          0          0     GIC-0 197 Level     12145000.gpio_chip
 25:          0          0          0          0     GIC-0 198 Level     12146000.gpio_chip
 26:          0          0          0          0     GIC-0 199 Level     12147000.gpio_chip
 27:          0          0          0          0     GIC-0 200 Level     12148000.gpio_chip
 28:          0          0          0          0     GIC-0 201 Level     12149000.gpio_chip
 29:          0          0          0          0     GIC-0 202 Level     1214a000.gpio_chip
 30:          0          0          0          0     GIC-0 203 Level     1214b000.gpio_chip
 31:          2          0          0          0     GIC-0 204 Level     1214c000.gpio_chip
 32:          0          0          0          0     GIC-0 205 Level     1214d000.gpio_chip
 33:          0          0          0          0     GIC-0 206 Level     1214e000.gpio_chip
 34:          0          0          0          0     GIC-0 207 Level     1214f000.gpio_chip
 35:          0          0          0          0     GIC-0 208 Level     12150000.gpio_chip
 36:          0          0          0          0     GIC-0 209 Level     12151000.gpio_chip
 37:          0          0          0          0     GIC-0 210 Level     12152000.gpio_chip
 38:          0          0          0          0     GIC-0 215 Level     180d3000.shub_gpio
 39:          0          0          0          0     GIC-0  43 Level     180b0000.rtc
 40:    5588734          0          0          0     GIC-0  68 Level     101c0000.ethernet
 42:        212          0          0          0     GIC-0 116 Level     xhci-hcd:usb1
 43:          0          0          0          0     GIC-0 117 Level     xhci-hcd:usb3
 44:       2314          0          0          0     GIC-0  58 Level     mmc0
 45:          0          0          0          0     GIC-0 106 Level     mmc1
 46:          0          0          0          0     GIC-0 107 Level     mmc2
 53:          0          0          0          0     GIC-0 113 Level     hiedmacv310
 55:          0          0          0          0     GIC-0  92 Level     VI_CAP0
 56:          0          0          0          0     GIC-0  93 Level     VI_PROC0
 57:          0          0          0          0     GIC-0  94 Level     VI_PROC1
 58:          0          0          0          0     GIC-0 118 Level     SLVS_EC0
 59:          0          0          0          0     GIC-0 120 Level     MIPI0
 60:     796266          0          0          0     GIC-0  77 Level     VPSS0
 61:      43022          0          0          0     GIC-0  78 Level     VPSS1
 62:     690722          0          0          0     GIC-0  75 Level     VGS0
 63:     222459          0          0          0     GIC-0  76 Level     VGS1
 64:          0          0          0          0     GIC-0  79 Level     GDC0
 65:          0          0          0          0     GIC-0  80 Level     GDC1
 66:          0          0          0          0     GIC-0  83 Level     DIS
 67:          0          0          0          0     GIC-0 184 Level     AVS
 68:          0          0          0          0     GIC-0  99 Level     VO Int
 69:          0          0          0          0     GIC-0 100 Level     HIFB Int
 70:          0          0          0          0     GIC-0  95 Level     MIPI_TX
 72:          0          0          0          0     GIC-0  71 Level     VEDU_0
 73:          0          0          0          0     GIC-0  72 Level     VEDU_1
 74:          0          0          0          0     GIC-0  73 Level     VEDU_2
 75:        652          0          0          0     GIC-0  81 Level     JPGE_0
 76:          0          0          0          0     GIC-0 123 Level     vdh_bd
 77:     912964          0          0          0     GIC-0 124 Level     vdh_pd
 78:     861008          0          0          0     GIC-0 126 Level     vdh_scd
 79:          0          0          0          0     GIC-0  84 Level     JPEGD_0
 80:     484599          0          0          0     GIC-0  90 Level     nnie0
 81:     484821          0          0          0     GIC-0  91 Level     nnie1
 82:          0          0          0          0     GIC-0 240 Level     DPU RECT
 83:          0          0          0          0     GIC-0 241 Level     DPU MATCH
 84:        326          0          0          0     GIC-0  88 Level     IVE
 86:          0          0          0          0     GIC-0 101 Level     AIO Interrupt
 87:          1          0          0          0     GIC-0 134 Level     11c00000.gpu
 88:          3          0          0          0     GIC-0  85 Level     tde_osr_isr
 89:          1          0          0          0     GIC-0 135 Level     11c00000.gpu
 90:          1          0          0          0     GIC-0 133 Level     11c00000.gpu
 97:          0          0          0          0     pl061   2 Edge      rst
193:          1          0          0          0     pl061   2 Edge      wiegand_data1
195:          1          0          0          0     pl061   4 Edge      wiegand_data0

IPI0:   1297810    2253123    4008151    9711865       Rescheduling interrupts
IPI1:        21         10         25         10       Function call interrupts
IPI2:         0          0          0          0       CPU stop interrupts
IPI3:         0          0          0          0       Timer broadcast interrupts
IPI4:         0          0          0          0       IRQ work interrupts
IPI5:         0          0          0          0       CPU wake-up interrupts
Err:          0

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      如何能解决上述问题?在网上找解决方法。

      1. 利用echo命令将cpu掩码写入/proc/irq/中断ID/smp_affinity文件中,即可实现修改某一中断的CPU亲和性。

      按照这个方法运行 echo 4 > /proc/irq/193/smp_affinity,结果提示如下错误:

      echo: write error: Input/output error

      再照这个问题的解决方法,答案令人失望,这是由硬件或操作系统决定的,无解!

      方法1失败。

      2. 不从应用层解决,着眼于内核层来寻求解决方法。内核中有这样一个函数:irq_set_affinity(clock_event_device->irq, cpumask);将irq 与 cpu 相关联,指出哪一个或几个 cpu 服务于该irq。

       按照这个方法修改模块代码,加入以下语句:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      struct cpumask cpumask;

      cpumask.bits[0] = (unsigned long)0x02;
      irq_set_affinity_hint(wiegand_in_devp->d0_irq, &cpumask);
      irq_set_affinity_hint(wiegand_in_devp->d1_irq, &cpumask);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      irq_set_affinity_hint函数位于kernel/irq/manage.c中,其调用了__irq_set_affinity函数,进而调用了irq_set_affinity函数。

      这个方法貌似根本解决了问题,但实际上编译模块并运行后,观察韦根的2个GPIO中断,还是分配到了CPU0上,cat /proc/irq/193/smp_affinity的结果依旧是f,没有任何改变。这是为什么?继续在内核代码中加入打印进行调试,发现问题出现在了这里(见下述红色粗体显示):

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
                bool force)
{
    struct irq_chip *chip = irq_data_get_irq_chip(data);
    struct irq_desc *desc = irq_data_to_desc(data);
    int ret = 0;
printk("111\n");
    if (!chip || !chip->irq_set_affinity)
        return -EINVAL;
printk("222\n");

    if (irq_can_move_pcntxt(data)) {
        ret = irq_do_set_affinity(data, mask, force);
    } else {
        irqd_set_move_pending(data);
        irq_copy_pending(desc, mask);
    }

    if (desc->affinity_notify) {
        kref_get(&desc->affinity_notify->kref);
        schedule_work(&desc->affinity_notify->work);
    }
    irqd_set(data, IRQD_AFFINITY_SET);

    return ret;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      实际上并没有往下运行,这应该是由于chip->irq_set_affinity为空导致的,但具体为何为空,应在哪里设置,怎样设置就需要进一步研究了……

发布了35 篇原创文章 · 获赞 12 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/104652480