[SPARC64]: Fix virq decomposition.
The dev_handle and dev_ino fields don't match up exactly to the traditional IMAP_IGN and IMAP_INO masks. So store them away in a table and look them up directly. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e83fb17f9b
commit
93b3238ef8
@ -87,7 +87,11 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY
|
|||||||
*/
|
*/
|
||||||
#define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist)
|
#define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist)
|
||||||
|
|
||||||
static unsigned int virt_to_real_irq_table[NR_IRQS];
|
static struct {
|
||||||
|
unsigned int irq;
|
||||||
|
unsigned int dev_handle;
|
||||||
|
unsigned int dev_ino;
|
||||||
|
} virt_to_real_irq_table[NR_IRQS];
|
||||||
|
|
||||||
static unsigned char virt_irq_alloc(unsigned int real_irq)
|
static unsigned char virt_irq_alloc(unsigned int real_irq)
|
||||||
{
|
{
|
||||||
@ -96,7 +100,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq)
|
|||||||
BUILD_BUG_ON(NR_IRQS >= 256);
|
BUILD_BUG_ON(NR_IRQS >= 256);
|
||||||
|
|
||||||
for (ent = 1; ent < NR_IRQS; ent++) {
|
for (ent = 1; ent < NR_IRQS; ent++) {
|
||||||
if (!virt_to_real_irq_table[ent])
|
if (!virt_to_real_irq_table[ent].irq)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ent >= NR_IRQS) {
|
if (ent >= NR_IRQS) {
|
||||||
@ -104,7 +108,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virt_to_real_irq_table[ent] = real_irq;
|
virt_to_real_irq_table[ent].irq = real_irq;
|
||||||
|
|
||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
@ -117,8 +121,8 @@ static void virt_irq_free(unsigned int virt_irq)
|
|||||||
if (virt_irq >= NR_IRQS)
|
if (virt_irq >= NR_IRQS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
real_irq = virt_to_real_irq_table[virt_irq];
|
real_irq = virt_to_real_irq_table[virt_irq].irq;
|
||||||
virt_to_real_irq_table[virt_irq] = 0;
|
virt_to_real_irq_table[virt_irq].irq = 0;
|
||||||
|
|
||||||
__bucket(real_irq)->virt_irq = 0;
|
__bucket(real_irq)->virt_irq = 0;
|
||||||
}
|
}
|
||||||
@ -126,7 +130,7 @@ static void virt_irq_free(unsigned int virt_irq)
|
|||||||
|
|
||||||
static unsigned int virt_to_real_irq(unsigned char virt_irq)
|
static unsigned int virt_to_real_irq(unsigned char virt_irq)
|
||||||
{
|
{
|
||||||
return virt_to_real_irq_table[virt_irq];
|
return virt_to_real_irq_table[virt_irq].irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -418,7 +422,6 @@ static void sun4v_irq_end(unsigned int virt_irq)
|
|||||||
static void sun4v_virq_enable(unsigned int virt_irq)
|
static void sun4v_virq_enable(unsigned int virt_irq)
|
||||||
{
|
{
|
||||||
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
||||||
unsigned int ino = bucket - &ivector_table[0];
|
|
||||||
|
|
||||||
if (likely(bucket)) {
|
if (likely(bucket)) {
|
||||||
unsigned long cpuid, dev_handle, dev_ino;
|
unsigned long cpuid, dev_handle, dev_ino;
|
||||||
@ -426,8 +429,8 @@ static void sun4v_virq_enable(unsigned int virt_irq)
|
|||||||
|
|
||||||
cpuid = irq_choose_cpu(virt_irq);
|
cpuid = irq_choose_cpu(virt_irq);
|
||||||
|
|
||||||
dev_handle = ino & IMAP_IGN;
|
dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
|
||||||
dev_ino = ino & IMAP_INO;
|
dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
|
||||||
|
|
||||||
err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
|
err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
|
||||||
if (err != HV_EOK)
|
if (err != HV_EOK)
|
||||||
@ -452,7 +455,6 @@ static void sun4v_virq_enable(unsigned int virt_irq)
|
|||||||
static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
|
static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
|
||||||
{
|
{
|
||||||
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
||||||
unsigned int ino = bucket - &ivector_table[0];
|
|
||||||
|
|
||||||
if (likely(bucket)) {
|
if (likely(bucket)) {
|
||||||
unsigned long cpuid, dev_handle, dev_ino;
|
unsigned long cpuid, dev_handle, dev_ino;
|
||||||
@ -460,8 +462,8 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
|
|||||||
|
|
||||||
cpuid = irq_choose_cpu(virt_irq);
|
cpuid = irq_choose_cpu(virt_irq);
|
||||||
|
|
||||||
dev_handle = ino & IMAP_IGN;
|
dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
|
||||||
dev_ino = ino & IMAP_INO;
|
dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
|
||||||
|
|
||||||
err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
|
err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
|
||||||
if (err != HV_EOK)
|
if (err != HV_EOK)
|
||||||
@ -474,14 +476,13 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
|
|||||||
static void sun4v_virq_disable(unsigned int virt_irq)
|
static void sun4v_virq_disable(unsigned int virt_irq)
|
||||||
{
|
{
|
||||||
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
||||||
unsigned int ino = bucket - &ivector_table[0];
|
|
||||||
|
|
||||||
if (likely(bucket)) {
|
if (likely(bucket)) {
|
||||||
unsigned long dev_handle, dev_ino;
|
unsigned long dev_handle, dev_ino;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dev_handle = ino & IMAP_IGN;
|
dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
|
||||||
dev_ino = ino & IMAP_INO;
|
dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
|
||||||
|
|
||||||
err = sun4v_vintr_set_valid(dev_handle, dev_ino,
|
err = sun4v_vintr_set_valid(dev_handle, dev_ino,
|
||||||
HV_INTR_DISABLED);
|
HV_INTR_DISABLED);
|
||||||
@ -495,7 +496,6 @@ static void sun4v_virq_disable(unsigned int virt_irq)
|
|||||||
static void sun4v_virq_end(unsigned int virt_irq)
|
static void sun4v_virq_end(unsigned int virt_irq)
|
||||||
{
|
{
|
||||||
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
|
||||||
unsigned int ino = bucket - &ivector_table[0];
|
|
||||||
struct irq_desc *desc = irq_desc + virt_irq;
|
struct irq_desc *desc = irq_desc + virt_irq;
|
||||||
|
|
||||||
if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||||
@ -505,8 +505,8 @@ static void sun4v_virq_end(unsigned int virt_irq)
|
|||||||
unsigned long dev_handle, dev_ino;
|
unsigned long dev_handle, dev_ino;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dev_handle = ino & IMAP_IGN;
|
dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
|
||||||
dev_ino = ino & IMAP_INO;
|
dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
|
||||||
|
|
||||||
err = sun4v_vintr_set_state(dev_handle, dev_ino,
|
err = sun4v_vintr_set_state(dev_handle, dev_ino,
|
||||||
HV_INTR_STATE_IDLE);
|
HV_INTR_STATE_IDLE);
|
||||||
@ -700,6 +700,7 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
|
|||||||
unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
|
unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
|
||||||
{
|
{
|
||||||
unsigned long sysino, hv_err;
|
unsigned long sysino, hv_err;
|
||||||
|
unsigned int virq;
|
||||||
|
|
||||||
BUG_ON(devhandle & devino);
|
BUG_ON(devhandle & devino);
|
||||||
|
|
||||||
@ -713,7 +714,12 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
|
|||||||
prom_halt();
|
prom_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
return sun4v_build_common(sysino, &sun4v_virq);
|
virq = sun4v_build_common(sysino, &sun4v_virq);
|
||||||
|
|
||||||
|
virt_to_real_irq_table[virq].dev_handle = devhandle;
|
||||||
|
virt_to_real_irq_table[virq].dev_ino = devino;
|
||||||
|
|
||||||
|
return virq;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_MSI
|
#ifdef CONFIG_PCI_MSI
|
||||||
|
Loading…
Reference in New Issue
Block a user