Fix interrupt routing for C8000 serial ports
Subsystems (2)
PATCH 1/1 Fix interrupt routing for C8000 serial ports
We can't use dev->mod_index for selecting the interrupt routing entry, because it's not an index into interrupt routing table. It will be even wrong on a machine with 2 CPUs (4 cores). But all needed information is contained in the PAT entries for the serial ports. mod[0] contains the iosapic address and mod_info has some indications for the interrupt input (at least it looks like it). This patch implements the searching for the right iosapic and uses this interrupt input information.
---
drivers/char/ipmi/ipmi_si_intf.c | 78 ++++++++++++++++++++++++++++++++++++++ arch/parisc/include/asm/parisc-device.h | 1 + arch/parisc/kernel/inventory.c | 1 + drivers/parisc/iosapic.c | 40 +++++++++++++++++++++---------- drivers/tty/serial/8250/8250_gsc.c | 4 ++-- 4 files changed, 32 insertions(+), 14 deletions(-)
arch/parisc/include/asm/parisc-device.h +1 -0
@@ -23,6 +23,7 @@ struct parisc_device {/* generic info returned from pdc_pat_cell_module() */ unsigned long mod_info;/* PAT specific - Misc Module info */ unsigned long pmod_loc;/* physical Module location */ +unsigned long mod0;#endif u64 dma_mask;/* DMA mask for I/O */ struct device dev;
arch/parisc/kernel/inventory.c +1 -0
@@ -211,6 +211,7 @@ pat_query_module(ulong pcell_loc, ulong mod_index)/* REVISIT: who is the consumer of this? not sure yet... */ dev->mod_info = pa_pdc_cell->mod_info;/* pass to PAT_GET_ENTITY() */ dev->pmod_loc = pa_pdc_cell->mod_location; + dev->mod0 = pa_pdc_cell->mod[0 ];register_parisc_device (dev);/* advertise device */
drivers/parisc/iosapic.c +28 -12
@@ -811,18 +811,28 @@ int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)return pcidev->irq; } -static struct iosapic_info *first_isi =NULL ; +static struct iosapic_info *iosapic_list;#ifdef CONFIG_64BIT -int iosapic_serial_irq (int num) +int iosapic_serial_irq (struct parisc_device *dev) { -struct iosapic_info *isi = first_isi; -struct irt_entry *irte =NULL ;/* only used if PAT PDC */ +struct iosapic_info *isi; +struct irt_entry *irte;struct vector_info *vi; -int isi_line;/* line used by device */ - +int cnt; +int intin; + + intin = (dev->mod_info >>24 ) &15 ; +/* lookup IRT entry for isi/slot/pin set */ - irte = &irt_cell[num]; +for (cnt =0 ; cnt < irt_num_entry; cnt++) { + irte = &irt_cell[cnt]; +if (COMPARE_IRTE_ADDR (irte, dev->mod0) && + irte->dest_iosapic_intin == intin) +break ; + } +if (cnt >= irt_num_entry) +return 0 ;/* no irq found, force polling */ DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n", irte,
@@ -834,11 +844,17 @@ int iosapic_serial_irq(int num) irte->src_seg_id, irte->dest_iosapic_intin, (u32) irte->dest_iosapic_addr); - isi_line = irte->dest_iosapic_intin; + +/* search for iosapic */ +for (isi = iosapic_list; isi; isi = isi->isi_next) +if (isi->isi_hpa == dev->mod0) +break ; +if (!isi) +return 0 ;/* no iosapic found, force polling */ /* get vector info for this input line */ - vi = isi->isi_vector + isi_line; -DBG_IRT ("iosapic_serial_irq: line %d vi 0x%p\n" , isi_line, vi); + vi = isi->isi_vector + intin; +DBG_IRT ("iosapic_serial_irq: line %d vi 0x%p\n" , iosapic_intin, vi);/* If this IRQ line has already been setup, skip it */ if (vi->irte)
@@ -941,8 +957,8 @@ void *iosapic_register(unsigned long hpa) vip->irqline = (unsigned char ) cnt; vip->iosapic = isi; } -if (!first_isi) - first_isi = isi; + isi->isi_next = iosapic_list; + iosapic_list = isi;return isi; }
drivers/tty/serial/8250/8250_gsc.c +2 -2
@@ -31,9 +31,9 @@ static int __init serial_init_chip(struct parisc_device *dev)int err;#ifdef CONFIG_64BIT -extern int iosapic_serial_irq (int cellnum); +extern int iosapic_serial_irq (struct parisc_device *dev);if (!dev->irq && (dev->id.sversion ==0xad )) - dev->irq =iosapic_serial_irq (dev->mod_index-1 ); + dev->irq =iosapic_serial_irq (dev);#endif if (!dev->irq) {
30.07.2013, 05:00, "Thomas Bogendoerfer" <[email protected]>:
Quoted 7 lines
We can't use
dev->mod_indexfor selecting the interrupt routing entry, because it's not an index into interrupt routing table. It will be even wrong on a machine with 2 CPUs (4 cores). But all needed information is contained in the PAT entries for the serial ports. mod[0] contains the iosapic address andmod_infohas some indications for the interrupt input (at least it looks like it). This patch implements the searching for the right iosapic and uses this interrupt input information.
Thomas,
Thanks for the fix! This indeed fixed serial on my c8000. Now, there is no need to use PDC_CONSOLE on this machine anymore.