Commit 8d57d3ad authored by David S. Miller's avatar David S. Miller

[SPARC64]: Stop using __do_IRQ().

Invoke the desc->handle_irq directly in the top-level dispatch,
just like other sophisticated ports.

This will allow us to decrease the cost of the MSI queue dispatch.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3d0a721f
...@@ -72,6 +72,10 @@ config ARCH_NO_VIRT_TO_BUS ...@@ -72,6 +72,10 @@ config ARCH_NO_VIRT_TO_BUS
config OF config OF
def_bool y def_bool y
config GENERIC_HARDIRQS_NO__DO_IRQ
bool
def_bool y
choice choice
prompt "Kernel page size" prompt "Kernel page size"
default SPARC64_PAGE_SIZE_8KB default SPARC64_PAGE_SIZE_8KB
......
...@@ -257,8 +257,8 @@ struct irq_handler_data { ...@@ -257,8 +257,8 @@ struct irq_handler_data {
unsigned long imap; unsigned long imap;
void (*pre_handler)(unsigned int, void *, void *); void (*pre_handler)(unsigned int, void *, void *);
void *pre_handler_arg1; void *arg1;
void *pre_handler_arg2; void *arg2;
}; };
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -346,7 +346,7 @@ static void sun4u_irq_disable(unsigned int virt_irq) ...@@ -346,7 +346,7 @@ static void sun4u_irq_disable(unsigned int virt_irq)
} }
} }
static void sun4u_irq_end(unsigned int virt_irq) static void sun4u_irq_eoi(unsigned int virt_irq)
{ {
struct irq_handler_data *data = get_irq_chip_data(virt_irq); struct irq_handler_data *data = get_irq_chip_data(virt_irq);
struct irq_desc *desc = irq_desc + virt_irq; struct irq_desc *desc = irq_desc + virt_irq;
...@@ -401,7 +401,7 @@ static void sun4v_irq_disable(unsigned int virt_irq) ...@@ -401,7 +401,7 @@ static void sun4v_irq_disable(unsigned int virt_irq)
"err(%d)\n", ino, err); "err(%d)\n", ino, err);
} }
static void sun4v_irq_end(unsigned int virt_irq) static void sun4v_irq_eoi(unsigned int virt_irq)
{ {
unsigned int ino = virt_irq_table[virt_irq].dev_ino; unsigned int ino = virt_irq_table[virt_irq].dev_ino;
struct irq_desc *desc = irq_desc + virt_irq; struct irq_desc *desc = irq_desc + virt_irq;
...@@ -478,7 +478,7 @@ static void sun4v_virq_disable(unsigned int virt_irq) ...@@ -478,7 +478,7 @@ static void sun4v_virq_disable(unsigned int virt_irq)
dev_handle, dev_ino, err); dev_handle, dev_ino, err);
} }
static void sun4v_virq_end(unsigned int virt_irq) static void sun4v_virq_eoi(unsigned int virt_irq)
{ {
struct irq_desc *desc = irq_desc + virt_irq; struct irq_desc *desc = irq_desc + virt_irq;
unsigned long dev_handle, dev_ino; unsigned long dev_handle, dev_ino;
...@@ -498,33 +498,11 @@ static void sun4v_virq_end(unsigned int virt_irq) ...@@ -498,33 +498,11 @@ static void sun4v_virq_end(unsigned int virt_irq)
dev_handle, dev_ino, err); dev_handle, dev_ino, err);
} }
static void run_pre_handler(unsigned int virt_irq)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
unsigned int ino;
ino = virt_irq_table[virt_irq].dev_ino;
if (likely(data->pre_handler)) {
data->pre_handler(ino,
data->pre_handler_arg1,
data->pre_handler_arg2);
}
}
static struct irq_chip sun4u_irq = { static struct irq_chip sun4u_irq = {
.typename = "sun4u", .typename = "sun4u",
.enable = sun4u_irq_enable, .enable = sun4u_irq_enable,
.disable = sun4u_irq_disable, .disable = sun4u_irq_disable,
.end = sun4u_irq_end, .eoi = sun4u_irq_eoi,
.set_affinity = sun4u_set_affinity,
};
static struct irq_chip sun4u_irq_ack = {
.typename = "sun4u+ack",
.enable = sun4u_irq_enable,
.disable = sun4u_irq_disable,
.ack = run_pre_handler,
.end = sun4u_irq_end,
.set_affinity = sun4u_set_affinity, .set_affinity = sun4u_set_affinity,
}; };
...@@ -532,7 +510,7 @@ static struct irq_chip sun4v_irq = { ...@@ -532,7 +510,7 @@ static struct irq_chip sun4v_irq = {
.typename = "sun4v", .typename = "sun4v",
.enable = sun4v_irq_enable, .enable = sun4v_irq_enable,
.disable = sun4v_irq_disable, .disable = sun4v_irq_disable,
.end = sun4v_irq_end, .eoi = sun4v_irq_eoi,
.set_affinity = sun4v_set_affinity, .set_affinity = sun4v_set_affinity,
}; };
...@@ -540,31 +518,33 @@ static struct irq_chip sun4v_virq = { ...@@ -540,31 +518,33 @@ static struct irq_chip sun4v_virq = {
.typename = "vsun4v", .typename = "vsun4v",
.enable = sun4v_virq_enable, .enable = sun4v_virq_enable,
.disable = sun4v_virq_disable, .disable = sun4v_virq_disable,
.end = sun4v_virq_end, .eoi = sun4v_virq_eoi,
.set_affinity = sun4v_virt_set_affinity, .set_affinity = sun4v_virt_set_affinity,
}; };
static void fastcall pre_flow_handler(unsigned int virt_irq,
struct irq_desc *desc)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
unsigned int ino = virt_irq_table[virt_irq].dev_ino;
data->pre_handler(ino, data->arg1, data->arg2);
handle_fasteoi_irq(virt_irq, desc);
}
void irq_install_pre_handler(int virt_irq, void irq_install_pre_handler(int virt_irq,
void (*func)(unsigned int, void *, void *), void (*func)(unsigned int, void *, void *),
void *arg1, void *arg2) void *arg1, void *arg2)
{ {
struct irq_handler_data *data = get_irq_chip_data(virt_irq); struct irq_handler_data *data = get_irq_chip_data(virt_irq);
struct irq_chip *chip = get_irq_chip(virt_irq); struct irq_desc *desc = irq_desc + 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 = func;
data->pre_handler_arg1 = arg1; data->arg1 = arg1;
data->pre_handler_arg2 = arg2; data->arg2 = arg2;
if (chip == &sun4u_irq_ack)
return;
set_irq_chip(virt_irq, &sun4u_irq_ack); desc->handle_irq = pre_flow_handler;
} }
unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
...@@ -582,7 +562,10 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) ...@@ -582,7 +562,10 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
if (!virt_irq) { if (!virt_irq) {
virt_irq = virt_irq_alloc(0, ino); virt_irq = virt_irq_alloc(0, ino);
bucket_set_virt_irq(__pa(bucket), virt_irq); bucket_set_virt_irq(__pa(bucket), virt_irq);
set_irq_chip(virt_irq, &sun4u_irq); set_irq_chip_and_handler_name(virt_irq,
&sun4u_irq,
handle_fasteoi_irq,
"IVEC");
} }
data = get_irq_chip_data(virt_irq); data = get_irq_chip_data(virt_irq);
...@@ -617,7 +600,9 @@ static unsigned int sun4v_build_common(unsigned long sysino, ...@@ -617,7 +600,9 @@ static unsigned int sun4v_build_common(unsigned long sysino,
if (!virt_irq) { if (!virt_irq) {
virt_irq = virt_irq_alloc(0, sysino); virt_irq = virt_irq_alloc(0, sysino);
bucket_set_virt_irq(__pa(bucket), virt_irq); bucket_set_virt_irq(__pa(bucket), virt_irq);
set_irq_chip(virt_irq, chip); set_irq_chip_and_handler_name(virt_irq, chip,
handle_fasteoi_irq,
"IVEC");
} }
data = get_irq_chip_data(virt_irq); data = get_irq_chip_data(virt_irq);
...@@ -665,7 +650,10 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) ...@@ -665,7 +650,10 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
virt_irq = virt_irq_alloc(devhandle, devino); virt_irq = virt_irq_alloc(devhandle, devino);
bucket_set_virt_irq(__pa(bucket), virt_irq); bucket_set_virt_irq(__pa(bucket), virt_irq);
set_irq_chip(virt_irq, &sun4v_virq);
set_irq_chip_and_handler_name(virt_irq, &sun4v_virq,
handle_fasteoi_irq,
"IVEC");
data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
if (unlikely(!data)) if (unlikely(!data))
...@@ -724,6 +712,7 @@ void handler_irq(int irq, struct pt_regs *regs) ...@@ -724,6 +712,7 @@ void handler_irq(int irq, struct pt_regs *regs)
: "memory"); : "memory");
while (bucket_pa) { while (bucket_pa) {
struct irq_desc *desc;
unsigned long next_pa; unsigned long next_pa;
unsigned int virt_irq; unsigned int virt_irq;
...@@ -731,7 +720,9 @@ void handler_irq(int irq, struct pt_regs *regs) ...@@ -731,7 +720,9 @@ void handler_irq(int irq, struct pt_regs *regs)
virt_irq = bucket_get_virt_irq(bucket_pa); virt_irq = bucket_get_virt_irq(bucket_pa);
bucket_clear_chain_pa(bucket_pa); bucket_clear_chain_pa(bucket_pa);
__do_IRQ(virt_irq); desc = irq_desc + virt_irq;
desc->handle_irq(virt_irq, desc);
bucket_pa = next_pa; bucket_pa = next_pa;
} }
......
...@@ -28,8 +28,15 @@ static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie) ...@@ -28,8 +28,15 @@ static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie)
unsigned long msi; unsigned long msi;
err = ops->dequeue_msi(pbm, msiqid, &head, &msi); err = ops->dequeue_msi(pbm, msiqid, &head, &msi);
if (likely(err > 0)) if (likely(err > 0)) {
__do_IRQ(pbm->msi_irq_table[msi - pbm->msi_first]); struct irq_desc *desc;
unsigned int virt_irq;
virt_irq = pbm->msi_irq_table[msi - pbm->msi_first];
desc = irq_desc + virt_irq;
desc->handle_irq(virt_irq, desc);
}
if (unlikely(err < 0)) if (unlikely(err < 0))
goto err_dequeue; goto err_dequeue;
...@@ -128,7 +135,8 @@ int sparc64_setup_msi_irq(unsigned int *virt_irq_p, ...@@ -128,7 +135,8 @@ int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
if (!*virt_irq_p) if (!*virt_irq_p)
goto out_err; goto out_err;
set_irq_chip(*virt_irq_p, &msi_irq); set_irq_chip_and_handler_name(*virt_irq_p, &msi_irq,
handle_simple_irq, "MSI");
err = alloc_msi(pbm); err = alloc_msi(pbm);
if (unlikely(err < 0)) if (unlikely(err < 0))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment