From ce76b9d295e240afe43507ca49196597382eeb59 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Mon, 8 May 2017 14:58:41 +0200 Subject: leon, pci-peripherals: SMP support by spin-locks and updated genirq --- c/src/lib/libbsp/sparc/shared/pci/gr_701.c | 67 ++++++++++++++----- c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c | 76 ++++++++++++++++------ c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c | 66 ++++++++++++++----- .../lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c | 68 ++++++++++++++----- c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c | 68 ++++++++++++++----- .../libbsp/sparc/shared/pci/gr_rasta_spw_router.c | 66 ++++++++++++++----- c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c | 68 ++++++++++++++----- c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c | 75 +++++++++++++++------ 8 files changed, 412 insertions(+), 142 deletions(-) diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_701.c b/c/src/lib/libbsp/sparc/shared/pci/gr_701.c index 40a0a2560e..a6c9ebcd5c 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_701.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_701.c @@ -23,6 +23,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -37,6 +38,16 @@ #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) + /* Offset from 0x80000000 (dual bus version) */ #define AHB1_BASE_ADDR 0x80000000 #define AHB1_IOAREA_BASE_ADDR 0x80100000 @@ -87,8 +98,9 @@ struct pci_bridge_regs { /* Private data structure for driver */ struct gr701_priv { /* Driver management */ - struct drvmgr_dev *dev; + struct drvmgr_dev *dev; char prefix[16]; + SPIN_DECLARE(devlock); struct pci_bridge_regs *pcib; struct amba_bridge_regs *ambab; @@ -200,7 +212,9 @@ void gr701_interrupt(void *arg) struct gr701_priv *priv = arg; unsigned int status; int irq = 0; + SPIN_ISR_IRQFLAGS(irqflags); + SPIN_LOCK(&priv->devlock, irqflags); while ( (status=priv->pcib->istatus) != 0 ) { priv->interrupt_cnt++; /* An interrupt was generated */ irq = status; @@ -208,6 +222,7 @@ void gr701_interrupt(void *arg) /* ACK interrupt */ priv->pcib->istatus = 0; } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ if ( irq ) @@ -347,6 +362,12 @@ int gr701_init1(struct drvmgr_dev *dev) if ((bar0_size == 0) || (bar1_size == 0)) return DRVMGR_ENORES; + /* Initialize spin-lock for this PCI perihperal device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + priv->genirq = genirq_init(16); if ( priv->genirq == NULL ) { free(priv); @@ -410,12 +431,17 @@ int ambapp_gr701_int_register( void *arg) { struct gr701_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; + + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); - status = genirq_register(priv->genirq, irq, handler, arg); + status = genirq_register(priv->genirq, irq, h); if ( status == 0 ) { /* Clear IRQ for first registered handler */ priv->pcib->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -434,7 +461,7 @@ int ambapp_gr701_int_register( } else if ( status == 1 ) status = DRVMGR_OK; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -446,10 +473,11 @@ int ambapp_gr701_int_unregister( void *arg) { struct gr701_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -457,11 +485,16 @@ int ambapp_gr701_int_unregister( priv->pcib->imask &= ~(1<genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -471,19 +504,19 @@ int ambapp_gr701_int_unmask( int irq) { struct gr701_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("GR-701 IRQ %d: enable\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_FAIL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ */ priv->pcib->imask |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -493,19 +526,19 @@ int ambapp_gr701_int_mask( int irq) { struct gr701_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("GR-701 IRQ %d: disable\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_FAIL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable IRQ */ priv->pcib->imask &= ~(1<devlock, irqflags); return DRVMGR_OK; } diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c b/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c index 3ba55c5442..7ff7206199 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c @@ -33,6 +33,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -45,6 +46,16 @@ #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) + /* Determines which PCI address the AHB masters on the GR740 board will * access when accessing the AHB to PCI window, it should be set so that the * masters can access the HOST RAM. @@ -98,7 +109,8 @@ struct gr740_grcg_regs { struct gr_cpci_gr740_priv { /* Driver management */ struct drvmgr_dev *dev; - char prefix[20]; + char prefix[16]; + SPIN_DECLARE(devlock); /* PCI */ pci_dev_t pcidev; @@ -213,10 +225,13 @@ void gr_cpci_gr740_isr(void *arg) struct gr_cpci_gr740_priv *priv = arg; unsigned int status, tmp; int irq, eirq; + SPIN_ISR_IRQFLAGS(irqflags); + tmp = status = priv->irq->ipend; /* DBG("GR-CPCI-GR740: IRQ 0x%x\n",status); */ + SPIN_LOCK(&priv->devlock, irqflags); for(irq = 0; irq < 32; irq++) { if (status & (1 << irq)) { if (irq == priv->eirq) { @@ -235,6 +250,7 @@ void gr_cpci_gr740_isr(void *arg) break; } } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller * still drives the IRQ @@ -461,11 +477,11 @@ int gr_cpci_gr740_init1(struct drvmgr_dev *dev) /* Generate Device prefix */ - strcpy(priv->prefix, "/dev/gr7400"); - priv->prefix[10] += dev->minor_drv; + strcpy(priv->prefix, "/dev/gr740_0"); + priv->prefix[11] += dev->minor_drv; mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[11] = '/'; - priv->prefix[12] = '\0'; + priv->prefix[12] = '/'; + priv->prefix[13] = '\0'; priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; priv->pcidev = devinfo->pcidev; @@ -485,6 +501,12 @@ int gr_cpci_gr740_init1(struct drvmgr_dev *dev) } printf(" IRQ: %d\n\n\n", devinfo->irq); + /* Initialize spin-lock for this PCI perihperal device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + /* Let user override which PCI address the AHB masters of the * GR740 board access when doing DMA to HOST RAM. The AHB masters * access the PCI Window of the AMBA bus, the MSB 2-bits of that address @@ -576,12 +598,17 @@ int ambapp_gr740_int_register( void *arg) { struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; - rtems_interrupt_disable(level); + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - status = genirq_register(priv->genirq, irq, handler, arg); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + + status = genirq_register(priv->genirq, irq, h); if (status == 0) { /* Clear IRQ for first registered handler */ priv->irq->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -600,7 +628,7 @@ int ambapp_gr740_int_register( } else if ( status == 1 ) status = 0; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -612,10 +640,11 @@ int ambapp_gr740_int_unregister( void *arg) { struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -623,11 +652,16 @@ int ambapp_gr740_int_unregister( priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -637,19 +671,19 @@ int ambapp_gr740_int_unmask( int irq) { struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("GR740 IRQ %d: unmask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ for first enabled handler only */ priv->irq->mask[0] |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -659,19 +693,19 @@ int ambapp_gr740_int_mask( int irq) { struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("GR740 IRQ %d: mask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable/mask IRQ */ priv->irq->mask[0] &= ~(1<devlock, irqflags); return DRVMGR_OK; } diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c b/c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c index 4a51884b49..cb78de4032 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c @@ -32,6 +32,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -44,6 +45,16 @@ #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) + /* Determines which PCI address the AHB masters on the LEON-N2X board will * access when accessing the AHB to PCI window, it should be set so that the * masters can access the HOST RAM. @@ -98,6 +109,7 @@ struct gr_cpci_leon4_n2x_priv { /* Driver management */ struct drvmgr_dev *dev; char prefix[20]; + SPIN_DECLARE(devlock); /* PCI */ pci_dev_t pcidev; @@ -213,10 +225,13 @@ void gr_cpci_leon4_n2x_isr(void *arg) struct gr_cpci_leon4_n2x_priv *priv = arg; unsigned int status, tmp; int irq, eirq; + SPIN_ISR_IRQFLAGS(irqflags); + tmp = status = priv->irq->ipend; /* DBG("GR-CPCI-LEON4-N2X: IRQ 0x%x\n",status); */ + SPIN_LOCK(&priv->devlock, irqflags); for(irq = 0; irq < 32; irq++) { if (status & (1 << irq)) { if (irq == priv->eirq) { @@ -235,6 +250,7 @@ void gr_cpci_leon4_n2x_isr(void *arg) break; } } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller * still drives the IRQ @@ -508,6 +524,12 @@ int gr_cpci_leon4_n2x_init1(struct drvmgr_dev *dev) } printf(" IRQ: %d\n\n\n", devinfo->irq); + /* Initialize spin-lock for this PCI perihperal device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + /* Let user override which PCI address the AHB masters of the * LEON4-N2X board access when doing DMA to HOST RAM. The AHB masters * access the PCI Window of the AMBA bus, the MSB 2-bits of that address @@ -599,12 +621,17 @@ int ambapp_leon4_n2x_int_register( void *arg) { struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; - rtems_interrupt_disable(level); + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - status = genirq_register(priv->genirq, irq, handler, arg); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + + status = genirq_register(priv->genirq, irq, h); if (status == 0) { /* Clear IRQ for first registered handler */ priv->irq->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -623,7 +651,7 @@ int ambapp_leon4_n2x_int_register( } else if ( status == 1 ) status = 0; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -635,10 +663,11 @@ int ambapp_leon4_n2x_int_unregister( void *arg) { struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -646,11 +675,16 @@ int ambapp_leon4_n2x_int_unregister( priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -660,19 +694,19 @@ int ambapp_leon4_n2x_int_unmask( int irq) { struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("LEON4-N2X IRQ %d: unmask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ for first enabled handler only */ priv->irq->mask[0] |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -682,19 +716,19 @@ int ambapp_leon4_n2x_int_mask( int irq) { struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("LEON4-N2X IRQ %d: mask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable/mask IRQ */ priv->irq->mask[0] &= ~(1<devlock, irqflags); return DRVMGR_OK; } diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c index 32891313ff..6d1f8f130f 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c @@ -23,6 +23,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -35,6 +36,16 @@ #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) + /*#define DEBUG 1*/ #ifdef DEBUG @@ -76,8 +87,9 @@ struct gr_rasta_adcdac_ver { /* Private data structure for driver */ struct gr_rasta_adcdac_priv { /* Driver management */ - struct drvmgr_dev *dev; + struct drvmgr_dev *dev; char prefix[20]; + SPIN_DECLARE(devlock); /* PCI */ pci_dev_t pcidev; @@ -193,10 +205,13 @@ void gr_rasta_adcdac_isr (void *arg) struct gr_rasta_adcdac_priv *priv = arg; unsigned int status, tmp; int irq; + SPIN_ISR_IRQFLAGS(irqflags); + tmp = status = priv->irq->ipend; /* DBG("GR-RASTA-ADCDAC: IRQ 0x%x\n",status); */ + SPIN_LOCK(&priv->devlock, irqflags); for(irq=0; irq<16; irq++) { if ( status & (1<genirq, irq); @@ -206,6 +221,7 @@ void gr_rasta_adcdac_isr (void *arg) break; } } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ if ( tmp ) @@ -411,6 +427,12 @@ int gr_rasta_adcdac_init1(struct drvmgr_dev *dev) if ((bar0_size == 0) || (bar1_size == 0)) return DRVMGR_ENORES; + /* Initialize spin-lock for this PCI perihperal device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + /* Let user override which PCI address the AHB masters of the * RASTA-ADCDAC board access when doing DMA to CPU RAM. The AHB masters * access the PCI Window of the AMBA bus, the MSB 4-bits of that address @@ -488,12 +510,17 @@ int ambapp_rasta_adcdac_int_register( void *arg) { struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; - rtems_interrupt_disable(level); + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - status = genirq_register(priv->genirq, irq, handler, arg); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + + status = genirq_register(priv->genirq, irq, h); if ( status == 0 ) { /* Clear IRQ for first registered handler */ priv->irq->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -512,7 +540,7 @@ int ambapp_rasta_adcdac_int_register( } else if ( status == 1 ) status = 0; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -524,10 +552,11 @@ int ambapp_rasta_adcdac_int_unregister( void *arg) { struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -535,11 +564,16 @@ int ambapp_rasta_adcdac_int_unregister( priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -549,19 +583,19 @@ int ambapp_rasta_adcdac_int_unmask( int irq) { struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-ADCDAC IRQ %d: unmask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ for first enabled handler only */ priv->irq->mask[0] |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -571,19 +605,19 @@ int ambapp_rasta_adcdac_int_mask( int irq) { struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-ADCDAC IRQ %d: mask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable/mask IRQ */ priv->irq->mask[0] &= ~(1<devlock, irqflags); return DRVMGR_OK; } diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c index 95bbee9902..1e424f67f0 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c @@ -23,6 +23,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -35,6 +36,16 @@ #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) + /* Determines which PCI address the AHB masters will access, it should be * set so that the masters can access the CPU RAM. Default is base of CPU RAM, * CPU RAM is mapped 1:1 to PCI space. @@ -108,8 +119,9 @@ struct gr_rasta_io_ver { /* Private data structure for driver */ struct gr_rasta_io_priv { /* Driver management */ - struct drvmgr_dev *dev; + struct drvmgr_dev *dev; char prefix[16]; + SPIN_DECLARE(devlock); /* PCI */ pci_dev_t pcidev; @@ -233,10 +245,13 @@ void gr_rasta_io_isr (void *arg) struct gr_rasta_io_priv *priv = arg; unsigned int status, tmp; int irq; + SPIN_ISR_IRQFLAGS(irqflags); + tmp = status = priv->irq->ipend; /* DBG("GR-RASTA-IO: IRQ 0x%x\n",status); */ + SPIN_LOCK(&priv->devlock, irqflags); for(irq=0; irq<16; irq++) { if ( status & (1<genirq, irq); @@ -246,6 +261,7 @@ void gr_rasta_io_isr (void *arg) break; } } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ if ( tmp ) @@ -590,6 +606,12 @@ int gr_rasta_io_init1(struct drvmgr_dev *dev) if ((bar0_size == 0) || (bar1_size == 0)) return DRVMGR_ENORES; + /* Initialize spin-lock for this PCI peripheral device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + /* Let user override which PCI address the AHB masters of the * GR-RASTA-IO board access when doing DMA to CPU RAM. The AHB masters * access the PCI Window of the AMBA bus, the MSB 4-bits of that address @@ -685,12 +707,17 @@ int ambapp_rasta_io_int_register( void *arg) { struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; - rtems_interrupt_disable(level); + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - status = genirq_register(priv->genirq, irq, handler, arg); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + + status = genirq_register(priv->genirq, irq, h); if ( status == 0 ) { /* Clear IRQ for first registered handler */ priv->irq->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -709,7 +737,7 @@ int ambapp_rasta_io_int_register( } else if ( status == 1 ) status = 0; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -721,10 +749,11 @@ int ambapp_rasta_io_int_unregister( void *arg) { struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -732,11 +761,16 @@ int ambapp_rasta_io_int_unregister( priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -746,19 +780,19 @@ int ambapp_rasta_io_int_unmask( int irq) { struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-IO IRQ %d: unmask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ for first enabled handler only */ priv->irq->mask[0] |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -768,19 +802,19 @@ int ambapp_rasta_io_int_mask( int irq) { struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-IO IRQ %d: mask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable/mask IRQ */ priv->irq->mask[0] &= ~(1<devlock, irqflags); return DRVMGR_OK; } diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c index 8bce1186ff..7f7e35085a 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c @@ -21,6 +21,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -32,6 +33,16 @@ #include #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) + /* Determines which PCI address the AHB masters will access, it should be * set so that the masters can access the CPU RAM. Default is base of CPU RAM, * CPU RAM is mapped 1:1 to PCI space. @@ -93,6 +104,7 @@ struct gr_rasta_spw_router_priv { /* Driver management */ struct drvmgr_dev *dev; char prefix[20]; + SPIN_DECLARE(devlock); /* PCI */ pci_dev_t pcidev; @@ -209,10 +221,13 @@ void gr_rasta_spw_router_isr(void *arg) struct gr_rasta_spw_router_priv *priv = arg; unsigned int status, tmp; int irq; + SPIN_ISR_IRQFLAGS(irqflags); + tmp = status = priv->irq->ipend; /* DBG("GR-RASTA-SPW-ROUTER: IRQ 0x%x\n",status); */ + SPIN_LOCK(&priv->devlock, irqflags); for(irq=0; irq<16; irq++) { if ( status & (1<genirq, irq); @@ -222,6 +237,7 @@ void gr_rasta_spw_router_isr(void *arg) break; } } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller * still drives the IRQ @@ -423,6 +439,12 @@ int gr_rasta_spw_router_init1(struct drvmgr_dev *dev) if (bar0_size == 0) return DRVMGR_ENORES; + /* Initialize spin-lock for this PCI peripheral device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + /* Let user override which PCI address the AHB masters of the * GR-RASTA-SPW board access when doing DMA to CPU RAM. The AHB masters * access the PCI Window of the AMBA bus, the MSB 4-bits of that address @@ -495,12 +517,17 @@ int ambapp_rasta_spw_router_int_register( void *arg) { struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; - rtems_interrupt_disable(level); + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - status = genirq_register(priv->genirq, irq, handler, arg); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + + status = genirq_register(priv->genirq, irq, h); if (status == 0) { /* Clear IRQ for first registered handler */ priv->irq->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -519,7 +547,7 @@ int ambapp_rasta_spw_router_int_register( } else if ( status == 1 ) status = 0; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -531,10 +559,11 @@ int ambapp_rasta_spw_router_int_unregister( void *arg) { struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -542,11 +571,16 @@ int ambapp_rasta_spw_router_int_unregister( priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -556,19 +590,19 @@ int ambapp_rasta_spw_router_int_unmask( int irq) { struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-SPW-ROUTER IRQ %d: unmask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ for first enabled handler only */ priv->irq->mask[0] |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -578,19 +612,19 @@ int ambapp_rasta_spw_router_int_mask( int irq) { struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-SPW-ROUTER IRQ %d: mask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable/mask IRQ */ priv->irq->mask[0] &= ~(1<devlock, irqflags); return DRVMGR_OK; } diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c index c8ba4c4962..6ca3c6be1a 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c @@ -23,6 +23,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -35,6 +36,16 @@ #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) + /* Determines which PCI address the AHB masters will access, it should be * set so that the masters can access the CPU RAM. Default is base of CPU RAM, * CPU RAM is mapped 1:1 to PCI space. @@ -104,8 +115,9 @@ struct gr_rasta_tmtc_ver { /* Private data structure for driver */ struct gr_rasta_tmtc_priv { /* Driver management */ - struct drvmgr_dev *dev; + struct drvmgr_dev *dev; char prefix[20]; + SPIN_DECLARE(devlock); /* PCI */ pci_dev_t pcidev; @@ -224,10 +236,13 @@ void gr_rasta_tmtc_isr (void *arg) struct gr_rasta_tmtc_priv *priv = arg; unsigned int status, tmp; int irq; + SPIN_ISR_IRQFLAGS(irqflags); + tmp = status = priv->irq->ipend; /* printk("GR-RASTA-TMTC: IRQ 0x%x\n",status); */ + SPIN_LOCK(&priv->devlock, irqflags); for(irq=0; irq<32; irq++) { if ( status & (1<genirq, irq); @@ -237,6 +252,7 @@ void gr_rasta_tmtc_isr (void *arg) break; } } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ if ( tmp ) @@ -602,6 +618,12 @@ int gr_rasta_tmtc_init1(struct drvmgr_dev *dev) if ((bar0_size == 0) || (bar1_size == 0)) return DRVMGR_ENORES; + /* Initialize spin-lock for this PCI peripheral device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + /* Let user override which PCI address the AHB masters of the * GR-RASTA-TMTC board access when doing DMA to CPU RAM. The AHB masters * access the PCI Window of the AMBA bus, the MSB 4-bits of that address @@ -689,12 +711,17 @@ int ambapp_rasta_tmtc_int_register( void *arg) { struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; - rtems_interrupt_disable(level); + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - status = genirq_register(priv->genirq, irq, handler, arg); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + + status = genirq_register(priv->genirq, irq, h); if ( status == 0 ) { /* Disable and clear IRQ for first registered handler */ priv->irq->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -713,7 +741,7 @@ int ambapp_rasta_tmtc_int_register( } else if ( status == 1 ) status = 0; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -725,10 +753,11 @@ int ambapp_rasta_tmtc_int_unregister( void *arg) { struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -737,11 +766,16 @@ int ambapp_rasta_tmtc_int_unregister( } else if ( status == 1 ) status = 0; - status = genirq_unregister(priv->genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -751,19 +785,19 @@ int ambapp_rasta_tmtc_int_unmask( int irq) { struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-TMTC IRQ %d: unmask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ */ priv->irq->mask[0] |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -773,19 +807,19 @@ int ambapp_rasta_tmtc_int_mask( int irq) { struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("RASTA-TMTC IRQ %d: mask\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_EINVAL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable IRQ */ priv->irq->mask[0] &= ~(1<devlock, irqflags); return DRVMGR_OK; } diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c b/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c index d56d8d7652..ec51ec312d 100644 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c +++ b/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c @@ -23,6 +23,7 @@ #include #include +#include /* spin-lock */ #include #include @@ -36,6 +37,15 @@ #include +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) /*#define DEBUG 1 */ @@ -60,8 +70,9 @@ struct gr_tmtc_1553_ver { /* Private data structure for driver */ struct gr_tmtc_1553_priv { /* Driver management */ - struct drvmgr_dev *dev; + struct drvmgr_dev *dev; char prefix[32]; + SPIN_DECLARE(devlock); /* PCI */ pci_dev_t pcidev; @@ -174,10 +185,13 @@ void gr_tmtc_1553_isr (void *arg) struct gr_tmtc_1553_priv *priv = arg; unsigned int status, tmp; int irq; + SPIN_ISR_IRQFLAGS(irqflags); + tmp = status = priv->irq->ipend; /* DBG("GR-RASTA-IO: IRQ 0x%x\n",status); */ + SPIN_LOCK(&priv->devlock, irqflags); for(irq=0; irq<16; irq++) { if ( status & (1<genirq, irq); @@ -187,6 +201,7 @@ void gr_tmtc_1553_isr (void *arg) break; } } + SPIN_UNLOCK(&priv->devlock, irqflags); /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ if ( tmp ) @@ -306,11 +321,11 @@ int gr_tmtc_1553_init1(struct drvmgr_dev *dev) /* Generate Device prefix */ - strcpy(priv->prefix, "/dev/tmtc1553_0/"); - priv->prefix[19] += dev->minor_drv; + strcpy(priv->prefix, "/dev/tmtc1553_0"); + priv->prefix[14] += dev->minor_drv; mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[20] = '/'; - priv->prefix[21] = '\0'; + priv->prefix[15] = '/'; + priv->prefix[16] = '\0'; priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; priv->pcidev = devinfo->pcidev; @@ -328,6 +343,12 @@ int gr_tmtc_1553_init1(struct drvmgr_dev *dev) if (bar0_size == 0) return DRVMGR_ENORES; + /* Initialize spin-lock for this PCI peripheral device. This is to + * protect the Interrupt Controller Registers. The genirq layer is + * protecting its own internals and ISR dispatching. + */ + SPIN_INIT(&priv->devlock, priv->prefix); + priv->genirq = genirq_init(16); if ( priv->genirq == NULL ) { free(priv); @@ -394,12 +415,17 @@ int ambapp_tmtc_1553_int_register( void *arg) { struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *h; - rtems_interrupt_disable(level); + h = genirq_alloc_handler(handler, arg); + if ( h == NULL ) + return DRVMGR_FAIL; - status = genirq_register(priv->genirq, irq, handler, arg); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + + status = genirq_register(priv->genirq, irq, h); if ( status == 0 ) { /* Disable and clear IRQ for first registered handler */ priv->irq->iclear = (1<devlock, irqflags); + genirq_free_handler(h); return DRVMGR_FAIL; } @@ -419,7 +446,7 @@ int ambapp_tmtc_1553_int_register( } else if ( status == 1 ) status = 0; - rtems_interrupt_enable(level); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); return status; } @@ -431,10 +458,11 @@ int ambapp_tmtc_1553_int_unregister( void *arg) { struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); int status; + void *handler; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); status = genirq_disable(priv->genirq, irq, isr, arg); if ( status == 0 ) { @@ -443,11 +471,16 @@ int ambapp_tmtc_1553_int_unregister( } else if ( status == 1 ) status = 0; - status = genirq_unregister(priv->genirq, irq, isr, arg); - if ( status != 0 ) + handler = genirq_unregister(priv->genirq, irq, isr, arg); + if ( handler == NULL ) status = DRVMGR_FAIL; + else + status = DRVMGR_OK; + + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - rtems_interrupt_enable(level); + if (handler) + genirq_free_handler(handler); return status; } @@ -457,19 +490,19 @@ int ambapp_tmtc_1553_int_unmask( int irq) { struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("TMTC-1553 IRQ %d: enable\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_FAIL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Enable IRQ */ priv->irq->mask[0] |= (1<devlock, irqflags); return DRVMGR_OK; } @@ -479,19 +512,19 @@ int ambapp_tmtc_1553_int_mask( int irq) { struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - rtems_interrupt_level level; + SPIN_IRQFLAGS(irqflags); DBG("TMTC-1553 IRQ %d: disable\n", irq); if ( genirq_check(priv->genirq, irq) ) return DRVMGR_FAIL; - rtems_interrupt_disable(level); + SPIN_LOCK_IRQ(&priv->devlock, irqflags); /* Disable IRQ */ priv->irq->mask[0] &= ~(1<devlock, irqflags); return DRVMGR_OK; } -- cgit v1.2.3