Skip to content
  • Tomasz Bursztyka's avatar
    isr: Normalize usage of device instance through ISR · 4dcfb553
    Tomasz Bursztyka authored
    
    
    The goal of this patch is to replace the 'void *' parameter by 'struct
    device *' if they use such variable or just 'const void *' on all
    relevant ISRs
    
    This will avoid not-so-nice const qualifier tweaks when device instances
    will be constant.
    
    Note that only the ISR passed to IRQ_CONNECT are of interest here.
    
    In order to do so, the script fix_isr.py below is necessary:
    
    from pathlib import Path
    import subprocess
    import pickle
    import mmap
    import sys
    import re
    import os
    
    cocci_template = """
    @r_fix_isr_0
    @
    type ret_type;
    identifier P;
    identifier D;
    @@
    -ret_type <!fn!>(void *P)
    +ret_type <!fn!>(const struct device *P)
    {
     ...
    (
     const struct device *D = (const struct device *)P;
    |
     const struct device *D = P;
    )
     ...
    }
    
    @r_fix_isr_1
    @
    type ret_type;
    identifier P;
    identifier D;
    @@
    -ret_type <!fn!>(void *P)
    +ret_type <!fn!>(const struct device *P)
    {
     ...
     const struct device *D;
     ...
    (
     D = (const struct device *)P;
    |
     D = P;
    )
     ...
    }
    
    @r_fix_isr_2
    @
    type ret_type;
    identifier A;
    @@
    -ret_type <!fn!>(void *A)
    +ret_type <!fn!>(const void *A)
    {
     ...
    }
    
    @r_fix_isr_3
    @
    const struct device *D;
    @@
    -<!fn!>((void *)D);
    +<!fn!>(D);
    
    @r_fix_isr_4
    @
    type ret_type;
    identifier D;
    identifier P;
    @@
    -ret_type <!fn!>(const struct device *P)
    +ret_type <!fn!>(const struct device *D)
    {
     ...
    (
    -const struct device *D = (const struct device *)P;
    |
    -const struct device *D = P;
    )
     ...
    }
    
    @r_fix_isr_5
    @
    type ret_type;
    identifier D;
    identifier P;
    @@
    -ret_type <!fn!>(const struct device *P)
    +ret_type <!fn!>(const struct device *D)
    {
     ...
    -const struct device *D;
    ...
    (
    -D = (const struct device *)P;
    |
    -D = P;
    )
     ...
    }
    """
    
    def find_isr(fn):
        db = []
        data = None
        start = 0
    
        try:
            with open(fn, 'r+') as f:
                data = str(mmap.mmap(f.fileno(), 0).read())
        except Exception as e:
            return db
    
        while True:
            isr = ""
            irq = data.find('IRQ_CONNECT', start)
            while irq > -1:
                p = 1
                arg = 1
                p_o = data.find('(', irq)
                if p_o < 0:
                    irq = -1
                    break;
    
                pos = p_o + 1
    
                while p > 0:
                    if data[pos] == ')':
                        p -= 1
                    elif data[pos] == '(':
                        p += 1
                    elif data[pos] == ',' and p == 1:
                        arg += 1
    
                    if arg == 3:
                        isr += data[pos]
    
                    pos += 1
    
                isr = isr.strip(',\\n\\t ')
                if isr not in db and len(isr) > 0:
                    db.append(isr)
    
                start = pos
                break
    
            if irq < 0:
                break
    
        return db
    
    def patch_isr(fn, isr_list):
        if len(isr_list) <= 0:
            return
    
        for isr in isr_list:
            tmplt = cocci_template.replace('<!fn!>', isr)
            with open('/tmp/isr_fix.cocci', 'w') as f:
                f.write(tmplt)
    
            cmd = ['spatch', '--sp-file', '/tmp/isr_fix.cocci', '--in-place', fn]
    
            subprocess.run(cmd)
    
    def process_files(path):
        if path.is_file() and path.suffix in ['.h', '.c']:
            p = str(path.parent) + '/' + path.name
            isr_list = find_isr(p)
            patch_isr(p, isr_list)
        elif path.is_dir():
            for p in path.iterdir():
                process_files(p)
    
    if len(sys.argv) < 2:
        print("You need to provide a dir/file path")
        sys.exit(1)
    
    process_files(Path(sys.argv[1]))
    
    And is run: ./fix_isr.py <zephyr root directory>
    
    Finally, some files needed manual fixes such.
    
    Fixes #27399
    
    Signed-off-by: default avatarTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
    4dcfb553
Loading