Skip to content

Commit

Permalink
Staging: vme: Pull common VME interrupt handling into core code
Browse files Browse the repository at this point in the history
Currently the VME callback infrastructure is replicated in each VME driver.
Move this common code into the VME core. Rename functions to fit in better
with naming of other VME functions.

Signed-off-by: Martyn Welch <martyn.welch@gefanuc.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Martyn Welch authored and Greg Kroah-Hartman committed Dec 11, 2009
1 parent beb9ccc commit c813f59
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 158 deletions.
78 changes: 15 additions & 63 deletions drivers/staging/vme/bridges/vme_ca91cx42.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
94 changes: 24 additions & 70 deletions drivers/staging/vme/bridges/vme_tsi148.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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)) {
Expand All @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit c813f59

Please sign in to comment.