Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 68625
b: refs/heads/master
c: 759f89e
h: refs/heads/master
i:
  68623: 9a81308
v: v3
  • Loading branch information
David S. Miller committed Oct 14, 2007
1 parent ad7b099 commit f946098
Show file tree
Hide file tree
Showing 8 changed files with 705 additions and 778 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a2cd15586e630b0870bf34783568d83901890743
refs/heads/master: 759f89e03c9e5656ff18c02e21b439506f7c0cdc
1 change: 1 addition & 0 deletions trunk/arch/sparc64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \
pci_psycho.o pci_sabre.o pci_schizo.o \
pci_sun4v.o pci_sun4v_asm.o pci_fire.o
obj-$(CONFIG_PCI_MSI) += pci_msi.o
obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o
obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
Expand Down
230 changes: 23 additions & 207 deletions trunk/arch/sparc64/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include <linux/seq_file.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <linux/msi.h>

#include <asm/ptrace.h>
#include <asm/processor.h>
Expand Down Expand Up @@ -92,39 +91,46 @@ static struct {
unsigned int dev_handle;
unsigned int dev_ino;
} virt_to_real_irq_table[NR_IRQS];
static DEFINE_SPINLOCK(virt_irq_alloc_lock);

static unsigned char virt_irq_alloc(unsigned int real_irq)
unsigned char virt_irq_alloc(unsigned int real_irq)
{
unsigned long flags;
unsigned char ent;

BUILD_BUG_ON(NR_IRQS >= 256);

spin_lock_irqsave(&virt_irq_alloc_lock, flags);

for (ent = 1; ent < NR_IRQS; ent++) {
if (!virt_to_real_irq_table[ent].irq)
break;
}
if (ent >= NR_IRQS) {
printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
return 0;
ent = 0;
} else {
virt_to_real_irq_table[ent].irq = real_irq;
}

virt_to_real_irq_table[ent].irq = real_irq;
spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);

return ent;
}

#ifdef CONFIG_PCI_MSI
static void virt_irq_free(unsigned int virt_irq)
void virt_irq_free(unsigned int virt_irq)
{
unsigned int real_irq;
unsigned long flags;

if (virt_irq >= NR_IRQS)
return;

real_irq = virt_to_real_irq_table[virt_irq].irq;
spin_lock_irqsave(&virt_irq_alloc_lock, flags);

virt_to_real_irq_table[virt_irq].irq = 0;

__bucket(real_irq)->virt_irq = 0;
spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);
}
#endif

Expand Down Expand Up @@ -217,27 +223,8 @@ struct irq_handler_data {
void (*pre_handler)(unsigned int, void *, void *);
void *pre_handler_arg1;
void *pre_handler_arg2;

u32 msi;
};

void sparc64_set_msi(unsigned int virt_irq, u32 msi)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);

if (data)
data->msi = msi;
}

u32 sparc64_get_msi(unsigned int virt_irq)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);

if (data)
return data->msi;
return 0xffffffff;
}

static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq)
{
unsigned int real_irq = virt_to_real_irq(virt_irq);
Expand Down Expand Up @@ -405,32 +392,6 @@ static void sun4v_irq_disable(unsigned int virt_irq)
}
}

#ifdef CONFIG_PCI_MSI
static void sun4u_msi_enable(unsigned int virt_irq)
{
sun4u_irq_enable(virt_irq);
unmask_msi_irq(virt_irq);
}

static void sun4u_msi_disable(unsigned int virt_irq)
{
mask_msi_irq(virt_irq);
sun4u_irq_disable(virt_irq);
}

static void sun4v_msi_enable(unsigned int virt_irq)
{
sun4v_irq_enable(virt_irq);
unmask_msi_irq(virt_irq);
}

static void sun4v_msi_disable(unsigned int virt_irq)
{
mask_msi_irq(virt_irq);
sun4v_irq_disable(virt_irq);
}
#endif

static void sun4v_irq_end(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
Expand Down Expand Up @@ -585,39 +546,6 @@ static struct irq_chip sun4v_irq = {
.set_affinity = sun4v_set_affinity,
};

static struct irq_chip sun4v_irq_ack = {
.typename = "sun4v+ack",
.enable = sun4v_irq_enable,
.disable = sun4v_irq_disable,
.ack = run_pre_handler,
.end = sun4v_irq_end,
.set_affinity = sun4v_set_affinity,
};

#ifdef CONFIG_PCI_MSI
static struct irq_chip sun4u_msi = {
.typename = "sun4u+msi",
.mask = mask_msi_irq,
.unmask = unmask_msi_irq,
.enable = sun4u_msi_enable,
.disable = sun4u_msi_disable,
.ack = run_pre_handler,
.end = sun4u_irq_end,
.set_affinity = sun4u_set_affinity,
};

static struct irq_chip sun4v_msi = {
.typename = "sun4v+msi",
.mask = mask_msi_irq,
.unmask = unmask_msi_irq,
.enable = sun4v_msi_enable,
.disable = sun4v_msi_disable,
.ack = run_pre_handler,
.end = sun4v_irq_end,
.set_affinity = sun4v_set_affinity,
};
#endif

static struct irq_chip sun4v_virq = {
.typename = "vsun4v",
.enable = sun4v_virq_enable,
Expand All @@ -626,42 +554,27 @@ static struct irq_chip sun4v_virq = {
.set_affinity = sun4v_virt_set_affinity,
};

static struct irq_chip sun4v_virq_ack = {
.typename = "vsun4v+ack",
.enable = sun4v_virq_enable,
.disable = sun4v_virq_disable,
.ack = run_pre_handler,
.end = sun4v_virq_end,
.set_affinity = sun4v_virt_set_affinity,
};

void irq_install_pre_handler(int virt_irq,
void (*func)(unsigned int, void *, void *),
void *arg1, void *arg2)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
struct irq_chip *chip;
struct irq_chip *chip = get_irq_chip(virt_irq);

if (WARN_ON(chip == &sun4v_irq || chip == &sun4v_virq)) {
printk(KERN_ERR "IRQ: Trying to install pre-handler on "
"sun4v irq %u\n", virt_irq);
return;
}

data->pre_handler = func;
data->pre_handler_arg1 = arg1;
data->pre_handler_arg2 = arg2;

chip = get_irq_chip(virt_irq);
if (chip == &sun4u_irq_ack ||
chip == &sun4v_irq_ack ||
chip == &sun4v_virq_ack
#ifdef CONFIG_PCI_MSI
|| chip == &sun4u_msi
|| chip == &sun4v_msi
#endif
)
if (chip == &sun4u_irq_ack)
return;

chip = (chip == &sun4u_irq ?
&sun4u_irq_ack :
(chip == &sun4v_irq ?
&sun4v_irq_ack : &sun4v_virq_ack));
set_irq_chip(virt_irq, chip);
set_irq_chip(virt_irq, &sun4u_irq_ack);
}

unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
Expand Down Expand Up @@ -765,103 +678,6 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
return virq;
}

#ifdef CONFIG_PCI_MSI
unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
unsigned int msi_start, unsigned int msi_end)
{
struct ino_bucket *bucket;
struct irq_handler_data *data;
unsigned long sysino;
unsigned int devino;

BUG_ON(tlb_type != hypervisor);

/* Find a free devino in the given range. */
for (devino = msi_start; devino < msi_end; devino++) {
sysino = sun4v_devino_to_sysino(devhandle, devino);
bucket = &ivector_table[sysino];
if (!bucket->virt_irq)
break;
}
if (devino >= msi_end)
return -ENOSPC;

sysino = sun4v_devino_to_sysino(devhandle, devino);
bucket = &ivector_table[sysino];
bucket->virt_irq = virt_irq_alloc(__irq(bucket));
*virt_irq_p = bucket->virt_irq;
set_irq_chip(bucket->virt_irq, &sun4v_msi);

data = get_irq_chip_data(bucket->virt_irq);
if (unlikely(data))
return devino;

data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
if (unlikely(!data)) {
virt_irq_free(*virt_irq_p);
return -ENOMEM;
}
set_irq_chip_data(bucket->virt_irq, data);

data->imap = ~0UL;
data->iclr = ~0UL;

return devino;
}

void sun4v_destroy_msi(unsigned int virt_irq)
{
virt_irq_free(virt_irq);
}

unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p,
unsigned int msi_start, unsigned int msi_end,
unsigned long imap_base, unsigned long iclr_base)
{
struct ino_bucket *bucket;
struct irq_handler_data *data;
unsigned long sysino;
unsigned int devino;

/* Find a free devino in the given range. */
for (devino = msi_start; devino < msi_end; devino++) {
sysino = (portid << 6) | devino;
bucket = &ivector_table[sysino];
if (!bucket->virt_irq)
break;
}
if (devino >= msi_end)
return -ENOSPC;

sysino = (portid << 6) | devino;
bucket = &ivector_table[sysino];
bucket->virt_irq = virt_irq_alloc(__irq(bucket));
*virt_irq_p = bucket->virt_irq;
set_irq_chip(bucket->virt_irq, &sun4u_msi);

data = get_irq_chip_data(bucket->virt_irq);
if (unlikely(data))
return devino;

data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
if (unlikely(!data)) {
virt_irq_free(*virt_irq_p);
return -ENOMEM;
}
set_irq_chip_data(bucket->virt_irq, data);

data->imap = (imap_base + (devino * 0x8UL));
data->iclr = (iclr_base + (devino * 0x8UL));

return devino;
}

void sun4u_destroy_msi(unsigned int virt_irq)
{
virt_irq_free(virt_irq);
}
#endif

void ack_bad_irq(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
Expand Down
Loading

0 comments on commit f946098

Please sign in to comment.