diff options
Diffstat (limited to 'drivers/staging/vme/bridges')
-rw-r--r-- | drivers/staging/vme/bridges/vme_ca91cx42.c | 78 | ||||
-rw-r--r-- | drivers/staging/vme/bridges/vme_tsi148.c | 94 |
2 files changed, 39 insertions, 133 deletions
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index 2810d80..74d54bb 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -53,9 +53,6 @@ struct mutex vme_int; /* * Only one VME interrupt can be * generated at a time, provide locking */ -struct mutex vme_irq; /* Locking for VME irq callback configuration */ - - static char driver_name[] = "vme_ca91cx42"; @@ -157,23 +154,13 @@ static u32 ca91cx42_LERR_irqhandler(void) static u32 ca91cx42_VIRQ_irqhandler(int stat) { int vec, i, serviced = 0; - void (*call)(int, int, void *); - void *priv_data; for (i = 7; i > 0; i--) { if (stat & (1 << i)) { vec = ioread32(ca91cx42_bridge->base + CA91CX42_V_STATID[i]) & 0xff; - call = ca91cx42_bridge->irq[i - 1].callback[vec].func; - priv_data = - ca91cx42_bridge->irq[i - 1].callback[vec].priv_data; - - if (call != NULL) - call(i, vec, priv_data); - else - printk("Spurilous VME interrupt, level:%x, " - "vector:%x\n", i, vec); + vme_irq_handler(ca91cx42_bridge, i, vec); serviced |= (1 << i); } @@ -234,6 +221,8 @@ static int ca91cx42_irq_init(struct vme_bridge *bridge) /* Initialise list for VME bus errors */ INIT_LIST_HEAD(&(bridge->vme_errors)); + mutex_init(&(bridge->irq_mtx)); + /* Disable interrupts from PCI to VME */ iowrite32(0, bridge->base + VINT_EN); @@ -281,66 +270,31 @@ static void ca91cx42_irq_exit(struct pci_dev *pdev) /* * Set up an VME interrupt */ -int ca91cx42_request_irq(int level, int statid, - void (*callback)(int level, int vector, void *priv_data), - void *priv_data) +void ca91cx42_irq_set(int level, int state, int sync) + { + struct pci_dev *pdev; u32 tmp; - mutex_lock(&(vme_irq)); - - if (ca91cx42_bridge->irq[level - 1].callback[statid].func) { - mutex_unlock(&(vme_irq)); - printk("VME Interrupt already taken\n"); - return -EBUSY; - } - - - ca91cx42_bridge->irq[level - 1].count++; - ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = priv_data; - ca91cx42_bridge->irq[level - 1].callback[statid].func = callback; - /* Enable IRQ level */ tmp = ioread32(ca91cx42_bridge->base + LINT_EN); - tmp |= CA91CX42_LINT_VIRQ[level]; - iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); - mutex_unlock(&(vme_irq)); - - return 0; -} - -/* - * Free VME interrupt - */ -void ca91cx42_free_irq(int level, int statid) -{ - u32 tmp; - struct pci_dev *pdev; - - mutex_lock(&(vme_irq)); - - ca91cx42_bridge->irq[level - 1].count--; - - /* Disable IRQ level if no more interrupts attached at this level*/ - if (ca91cx42_bridge->irq[level - 1].count == 0) { - tmp = ioread32(ca91cx42_bridge->base + LINT_EN); + if (state == 0) tmp &= ~CA91CX42_LINT_VIRQ[level]; - iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); + else + tmp |= CA91CX42_LINT_VIRQ[level]; + iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); + + if ((state == 0) && (sync != 0)) { pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); synchronize_irq(pdev->irq); } - - ca91cx42_bridge->irq[level - 1].callback[statid].func = NULL; - ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = NULL; - - mutex_unlock(&(vme_irq)); } -int ca91cx42_generate_irq(int level, int statid) +int ca91cx42_irq_generate(int level, int statid) { u32 tmp; @@ -1064,7 +1018,6 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) init_waitqueue_head(&dma_queue); init_waitqueue_head(&iack_queue); mutex_init(&(vme_int)); - mutex_init(&(vme_irq)); mutex_init(&(vme_rmw)); ca91cx42_bridge->parent = &(pdev->dev); @@ -1181,9 +1134,8 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; #endif - ca91cx42_bridge->request_irq = ca91cx42_request_irq; - ca91cx42_bridge->free_irq = ca91cx42_free_irq; - ca91cx42_bridge->generate_irq = ca91cx42_generate_irq; + ca91cx42_bridge->irq_set = ca91cx42_irq_set; + ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; #if 0 ca91cx42_bridge->lm_set = ca91cx42_lm_set; ca91cx42_bridge->lm_get = ca91cx42_lm_get; diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c index 4d20125..5b5c73e 100644 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ b/drivers/staging/vme/bridges/vme_tsi148.c @@ -77,8 +77,6 @@ struct mutex vme_int; /* * Only one VME interrupt can be * generated at a time, provide locking */ -struct mutex vme_irq; /* Locking for VME irq callback configuration */ - static char driver_name[] = "vme_tsi148"; @@ -251,8 +249,6 @@ static u32 tsi148_IACK_irqhandler(void) static u32 tsi148_VIRQ_irqhandler(u32 stat) { int vec, i, serviced = 0; - void (*call)(int, int, void *); - void *priv_data; for (i = 7; i > 0; i--) { if (stat & (1 << i)) { @@ -265,15 +261,7 @@ static u32 tsi148_VIRQ_irqhandler(u32 stat) vec = ioread8(tsi148_bridge->base + TSI148_LCSR_VIACK[i] + 3); - call = tsi148_bridge->irq[i - 1].callback[vec].func; - priv_data = - tsi148_bridge->irq[i-1].callback[vec].priv_data; - - if (call != NULL) - call(i, vec, priv_data); - else - printk("Spurilous VME interrupt, level:%x, " - "vector:%x\n", i, vec); + vme_irq_handler(tsi148_bridge, i, vec); serviced |= (1 << i); } @@ -353,6 +341,8 @@ static int tsi148_irq_init(struct vme_bridge *bridge) /* Initialise list for VME bus errors */ INIT_LIST_HEAD(&(bridge->vme_errors)); + mutex_init(&(bridge->irq_mtx)); + result = request_irq(pdev->irq, tsi148_irqhandler, IRQF_SHARED, @@ -432,55 +422,15 @@ int tsi148_iack_received(void) } /* - * Set up an VME interrupt + * Configure VME interrupt */ -int tsi148_request_irq(int level, int statid, - void (*callback)(int level, int vector, void *priv_data), - void *priv_data) +void tsi148_irq_set(int level, int state, int sync) { - u32 tmp; - - mutex_lock(&(vme_irq)); - - if(tsi148_bridge->irq[level - 1].callback[statid].func) { - mutex_unlock(&(vme_irq)); - printk("VME Interrupt already taken\n"); - return -EBUSY; - } - - - tsi148_bridge->irq[level - 1].count++; - tsi148_bridge->irq[level - 1].callback[statid].priv_data = priv_data; - tsi148_bridge->irq[level - 1].callback[statid].func = callback; - - /* Enable IRQ level */ - tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO); - tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; - iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO); - - tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN); - tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; - iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN); - - mutex_unlock(&(vme_irq)); - - return 0; -} - -/* - * Free VME interrupt - */ -void tsi148_free_irq(int level, int statid) -{ - u32 tmp; struct pci_dev *pdev; + u32 tmp; - mutex_lock(&(vme_irq)); - - tsi148_bridge->irq[level - 1].count--; - - /* Disable IRQ level if no more interrupts attached at this level*/ - if (tsi148_bridge->irq[level - 1].count == 0) { + /* We need to do the ordering differently for enabling and disabling */ + if (state == 0) { tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN); tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1]; iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN); @@ -489,22 +439,28 @@ void tsi148_free_irq(int level, int statid) tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1]; iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO); - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + if (sync != 0) { + pdev = container_of(tsi148_bridge->parent, + struct pci_dev, dev); - synchronize_irq(pdev->irq); - } - - tsi148_bridge->irq[level - 1].callback[statid].func = NULL; - tsi148_bridge->irq[level - 1].callback[statid].priv_data = NULL; + synchronize_irq(pdev->irq); + } + } else { + tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO); + tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; + iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO); - mutex_unlock(&(vme_irq)); + tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN); + tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; + iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN); + } } /* * Generate a VME bus interrupt at the requested level & vector. Wait for * interrupt to be acked. */ -int tsi148_generate_irq(int level, int statid) +int tsi148_irq_generate(int level, int statid) { u32 tmp; @@ -2333,7 +2289,6 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) init_waitqueue_head(&dma_queue[1]); init_waitqueue_head(&iack_queue); mutex_init(&(vme_int)); - mutex_init(&(vme_irq)); mutex_init(&(vme_rmw)); tsi148_bridge->parent = &(pdev->dev); @@ -2481,9 +2436,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) tsi148_bridge->dma_list_add = tsi148_dma_list_add; tsi148_bridge->dma_list_exec = tsi148_dma_list_exec; tsi148_bridge->dma_list_empty = tsi148_dma_list_empty; - tsi148_bridge->request_irq = tsi148_request_irq; - tsi148_bridge->free_irq = tsi148_free_irq; - tsi148_bridge->generate_irq = tsi148_generate_irq; + tsi148_bridge->irq_set = tsi148_irq_set; + tsi148_bridge->irq_generate = tsi148_irq_generate; tsi148_bridge->lm_set = tsi148_lm_set; tsi148_bridge->lm_get = tsi148_lm_get; tsi148_bridge->lm_attach = tsi148_lm_attach; |