Index: linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c =================================================================== @ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:279 @ { int ret; - ret = request_irq(port->irq, ulite_isr, IRQF_SHARED, "uartlite", port); - if (ret) - return ret; + //ret = request_irq(port->irq, ulite_isr, IRQF_NO_THREAD, "uartlite", port); + ret = request_any_context_irq(port->irq, ulite_isr, 0, "uartlite", port); + if (ret < 0){ + printk(KERN_ERR "uartlite: request_any_context_irq returned with error %d\n",ret); + return ret; + } ret = readb(port->membase + ULITE_STATUS); Index: linux-3.12.33-rt47-i386/drivers/uio/uio_scu3.c =================================================================== --- linux-3.12.33-rt47-i386.orig/drivers/uio/uio_scu3.c 2015-09-04 11:32:09.480247712 +0200 +++ linux-3.12.33-rt47-i386/drivers/uio/uio_scu3.c 2015-09-15 17:03:57.388810674 +0200 @ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:159 @ } static DEVICE_ATTR(scu3_id, S_IRUGO, show_id,0); + + + + +/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */ +/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */ +/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ + +DEFINE_RAW_SPINLOCK(scu3_vpic_lock); +static int scu3_vpic_irq_base; + +static void mask_scu3_vpic_irq(struct irq_data *data) +{ + unsigned long flags; +// printk(KERN_INFO PFX "mask_scu3_vpic_irq irq=0x%x hwirq=0x%lx mask=0x%x chip=0x%p chip_data=0x%p\n" +// ,data->irq +// ,data->hwirq +// ,data->mask +// ,data->chip +// ,data->chip_data +// ); + raw_spin_lock_irqsave(&scu3_vpic_lock, flags); + SCU3_INT_FRG_REG &= ~data->mask; + raw_spin_unlock_irqrestore(&scu3_vpic_lock, flags); + +} +static void unmask_scu3_vpic_irq(struct irq_data *data) +{ + unsigned long flags; +// printk(KERN_INFO PFX "unmask_scu3_vpic_irq irq=0x%x hwirq=0x%lx mask=0x%x chip=0x%p chip_data=0x%p\n" +// ,data->irq +// ,data->hwirq +// ,data->mask +// ,data->chip +// ,data->chip_data +// ); + raw_spin_lock_irqsave(&scu3_vpic_lock, flags); + SCU3_INT_FRG_REG |= data->mask; + raw_spin_unlock_irqrestore(&scu3_vpic_lock, flags); +} +static struct irq_chip scu3_vpic_chip __read_mostly = { + .name = "scu3-vpic", + .irq_mask = mask_scu3_vpic_irq, + .irq_unmask = unmask_scu3_vpic_irq, +}; + + +// Die Instanz des vpic besteht aus drei allocierten Interruptnummern +// und deren irq_desc-Datenstrukturen. +// Die scu3_vpic_irq_base enthält den Anfang des Nummernbereichs +int init_scu3_vpic(void) +{ + scu3_vpic_irq_base = irq_alloc_descs(-1, 0, 3, 0); + if(scu3_vpic_irq_base < 0) { + printk(KERN_ERR PFX "irq_alloc_descs failed %d\n",scu3_vpic_irq_base); + return -1; + } + printk(KERN_INFO PFX "irq_alloc_descs from: %d\n",scu3_vpic_irq_base); + return 0; +} +// Die einzelnen virt. irqs werden als nested_thread-irqs initialisiert. +// 'vpic_irq' ist der relative offset ab scu3_vpic_irq_base 0..2 +// 'mask' ist die hw-bit-maske fur das SCU3_INT_FRG_REG +int init_scu3_vpic_irq(int vpic_irq, unsigned mask) +{ + int ret; + struct irq_desc *desc; + int irq = scu3_vpic_irq_base + vpic_irq; + + ret = irq_set_chip(irq, &scu3_vpic_chip); + if(ret) { + printk(KERN_ERR PFX "irq_set_chip failed %d\n",ret); + return -1; + } + + // /home/husteret/build/SYS/SfcLeanOs-RT/trunk/Src/kernel/Objs/i486-linux/linux-3.12.33-rt47-x86_64/drivers/gpio/gpio-davinci.c:442 + //irq_set_handler(irq, handle_simple_irq); + + // ../gpio/gpio-adnp.c:420 + // set thread_fn without extra thread + // !!!! uartlite must use request_any_context_irq instead of request_irq + // !!!! request_any_context_irq delivers ret-val 1 != 0 !!! + irq_set_nested_thread(irq, true); + irq_set_noprobe(irq); + //irq_settings_set_nothread(desc); + + desc = irq_to_desc(irq); + irq_desc_get_irq_data(desc)->mask = mask; //set the bitmask for + return irq; +} + +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */ +/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */ +/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */ + + + static irqreturn_t uio_scu3_handler(int irq, struct uio_info *dev_info) { - u16 req=SCU3_INT_STATUS_REG & MY_INTS; //INT_MASK; + u16 allreq = SCU3_INT_STATUS_REG; - if(!req) /* shared irq? */ + if(allreq & SCU3_INT_SER_1) handle_nested_irq(scu3_vpic_irq_base+0); + if(allreq & SCU3_INT_SER_2) handle_nested_irq(scu3_vpic_irq_base+1); + if(allreq & SCU3_INT_SER_3) handle_nested_irq(scu3_vpic_irq_base+2); + + if((allreq & MY_INTS)==0) /* shared irq? */ { + // !!!!!!!! Achtung !!!!!! + // Wir muessen hier IRQ_NONE liefern damit uio den userhandler nicht aufruft. + // Aus Sicht des Kernels ist das aber sehr wahrsch. falsch weil der int durch + // eine sio ausgeloest wurde, d.h. es wurde etwas ge-HANDLED + // Dies ist hoffenlich nicht so tragisch weil der kernel dank vpic keinen shared-int + // behandeln muss return IRQ_NONE; } SCU3_INT_FRG_REG &= ~(MY_INTS); //INT_OFF_MASK; return IRQ_HANDLED; -// old -// static irqreturn_t uio_scu3_handler(int irq, struct uio_info *dev_info) -// { -// u16 req=((SCU3_INT_STATUS_REG & 0xff) << 8) | (SCU3_FI_STATUS_REG & 0xff); -// -// if(!req) /* shared irq? */ -// { -// return IRQ_NONE; -// } -// //SCU3_FI_FRG_REG = 0; nicht sperren damit weiterhin alle flanken sichtbar -// SCU3_FI_EOI_REG = 0xff; //Fast Input Ints mit EOI beseitigen -// SCU3_INT_FRG_REG = 0; //Hier gehts nicht mit EOI weil die Quellen noch anstehen -// return IRQ_HANDLED; -/* Fast IO register -Achtung!! see Fast_input_bit.vhd -1. komisches interupt-Sperrverhalten. -2. kein Intrequest Register - - -1. Beim sperren der ints mit SCU3_FI_FRG_REG=0 wird die Int-erkennung halb -ausgeschaltet. Zwischenzeitlich anfallende Ints werden bei der wiederfreigabe -genau dann gemeldet wenn der Pegel vor der Sperre ungleich dem Pegel hinter der -Sperre ist. -T 1 2 3 4 5 6 7 8 9 -INPUT_REG --______---- -----____---------- ---____--_______ - - | | | | - v v v v - -FRG_REG _------------ -------______--- -----______- - - | | | | | | | - v v v v v v v kein int - -STATUS_REG __i--__i--__ _____i-______i---__ ___i-___________ - ^ ^ ^ -EOI_REG _____-____-_ _________________-_ - -Im Bsp. wird also zum Zeitpunkt 5 ein Int ausgeloest, zum Zeitpunkt 9 -jedoch nicht, weil der Pegel vor der Int-Sperre einmal ungleich (T=5) und beim -zweiten Mal identisch (T=9) mit dem aktuellen Pegel ist. - -Dies fuehrt im schlimmsten Fall dazu, dass die Software auf dem falschen Pegel -festklemmt. Im Bsp. erkennt die Pollingloop die Pegel bei T=6 u. T=7, aber -T=8 kommt ausgerechnet in dem Zeitraum zwischen Pollingloop Ende und -Int-Freigabe. -Abhilfe: FRG_REG nicht verwenden. (Lediglich zur Komplettsperre) - - -2. Das STATUS_REG ist nur dann verfuegbar wenn das FRG_REG=1 und solange noch -kein EOI ausgeloest wurde. -*/ } + static struct uio_info *uinfo2 = 0; static dma_addr_t dmem_baddr = 0; //bus addr static void *dmem_vaddr = 0; @ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:372 @ printk(KERN_INFO PFX "sio_init %d: pres %p\n", num,&uart_res); -// pres[0].flags = IORESOURCE_MEM; -// pres[0].start = base; -// pres[0].end = base + 16; -// pres[1].flags = IORESOURCE_IRQ; -// pres[1].start = irq; -// pres[1].end = irq; - - SCU3_INT_FRG_REG |= intmsk; //sio_int_masks[num]; + //SCU3_INT_FRG_REG |= intmsk; //sio_int_masks[num]; // pdev = platform_device_register_simple("uartlite", num, pres, 2); pdev = platform_device_register_simple("uartlite", num, @ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:384 @ { printk(KERN_ERR PFX "Unable to register platform device '%s'#%d: err=%d\n", "uartlite", num, ret); - SCU3_INT_FRG_REG &= ~intmsk;//sio_int_masks[num]; + //SCU3_INT_FRG_REG &= ~intmsk;//sio_int_masks[num]; } else { @ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:437 @ printk(KERN_INFO PFX "1 pdev->irq = %d\n",pdev->irq); //info->irq_flags = IRQF_DISABLED | IRQF_SHARED; // see below: SCU3_INT_FRG_REG = 0; - info->irq_flags = IRQF_SHARED; + info->irq_flags = 0; //IRQF_SHARED; info->handler = uio_scu3_handler; mmio_start = pci_resource_start(pdev, 0); //resource_size_t = phys_addr_t = u64/u32 @ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:523 @ printk(KERN_ERR PFX "bad uio_register_device\n"); goto out_err; } - printk(KERN_INFO PFX "sio_init\n"); initState|=8; //device registered + printk(KERN_INFO PFX "sio_init\n"); + /* vpic */ + do{ //allow early exit + struct Tab {unsigned ofs,mask,msk2;}; + struct Tab sioResrc[]={ + {0x500000,SCU3_INT_SER_1,0x10}, + {0x600000,SCU3_INT_SER_2,0x20}, + {0xf00000,SCU3_INT_SER_3,0x40}, + }; + int i; + if( init_scu3_vpic() < 0) break; - if(sio_init(0, mmio_start+0x500000, pci_irq,SCU3_INT_SER_1)==0) - initState|=0x10; //sio0 initialized - if(sio_init(1, mmio_start+0x600000, pci_irq,SCU3_INT_SER_2)==0) - initState|=0x20; //sio1 initialized - if(sio_init(2, mmio_start+0xf00000, pci_irq,SCU3_INT_SER_3)==0) - initState|=0x40; //sio2 initialized + for(i=0;i<3;i++){ + int irq = init_scu3_vpic_irq(i,sioResrc[i].mask); + if( irq < 0) break; + + // !!!! uartlite must use request_any_context_irq instead of request_irq + // !!!! request_any_context_irq delivers ret-val 1 != 0 !!! + if(sio_init(i, mmio_start+sioResrc[i].ofs, irq,0)==0) + initState|=sioResrc[i].msk2; //sio0 initialized + } + }while(0); if(dmem_init(pdev)==0) initState|=0x80; //dma memory