* Created, December 13, 2000 by Wayne Holm
* End Change Activity
*/
+#include <linux/config.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/threads.h>
#include <asm/iseries/it_lp_queue.h>
#include "irq.h"
-#include "pci.h"
#include "call_pci.h"
#if defined(CONFIG_SMP)
printk(KERN_ERR "pci_event_handler: NULL event received\n");
}
+/*
+ * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
+ * It must be called before the bus walk.
+ */
+void __init iSeries_init_IRQ(void)
+{
+ /* Register PCI event handler and open an event path */
+ int ret;
+
+ ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
+ &pci_event_handler);
+ if (ret == 0) {
+ ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+ if (ret != 0)
+ printk(KERN_ERR "iseries_init_IRQ: open event path "
+ "failed with rc 0x%x\n", ret);
+ } else
+ printk(KERN_ERR "iseries_init_IRQ: register handler "
+ "failed with rc 0x%x\n", ret);
+}
+
#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+ unsigned int rirq = virt_irq_to_real_map[irq];
/* The IRQ has already been locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+ unsigned int rirq = virt_irq_to_real_map[irq];
bus = REAL_IRQ_TO_BUS(rirq);
function = REAL_IRQ_TO_FUNC(rirq);
for_each_irq (irq) {
irq_desc_t *desc = get_irq_desc(irq);
- if (desc && desc->chip && desc->chip->startup) {
+ if (desc && desc->handler && desc->handler->startup) {
spin_lock_irqsave(&desc->lock, flags);
- desc->chip->startup(irq);
+ desc->handler->startup(irq);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+ unsigned int rirq = virt_irq_to_real_map[irq];
/* irq should be locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
{
u32 bus, dev_id, function, mask;
const u32 sub_bus = 0;
- unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+ unsigned int rirq = virt_irq_to_real_map[irq];
/* The IRQ has already been locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
static void iseries_end_IRQ(unsigned int irq)
{
- unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+ unsigned int rirq = virt_irq_to_real_map[irq];
HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
(REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
}
-static struct irq_chip iseries_pic = {
- .typename = "iSeries irq controller",
- .startup = iseries_startup_IRQ,
- .shutdown = iseries_shutdown_IRQ,
- .unmask = iseries_enable_IRQ,
- .mask = iseries_disable_IRQ,
- .eoi = iseries_end_IRQ
+static hw_irq_controller iSeries_IRQ_handler = {
+ .typename = "iSeries irq controller",
+ .startup = iseries_startup_IRQ,
+ .shutdown = iseries_shutdown_IRQ,
+ .enable = iseries_enable_IRQ,
+ .disable = iseries_disable_IRQ,
+ .end = iseries_end_IRQ
};
/*
* Note that sub_bus is always 0 (at the moment at least).
*/
int __init iSeries_allocate_IRQ(HvBusNumber bus,
- HvSubBusNumber sub_bus, u32 bsubbus)
+ HvSubBusNumber sub_bus, HvAgentId dev_id)
{
+ int virtirq;
unsigned int realirq;
- u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
- u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
+ u8 idsel = (dev_id >> 4);
+ u8 function = dev_id & 7;
realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
+ function;
+ virtirq = virt_irq_create_mapping(realirq);
- return irq_create_mapping(NULL, realirq);
+ irq_desc[virtirq].handler = &iSeries_IRQ_handler;
+ return virtirq;
}
#endif /* CONFIG_PCI */
/*
* Get the next pending IRQ.
*/
-unsigned int iSeries_get_irq(struct pt_regs *regs)
+int iSeries_get_irq(struct pt_regs *regs)
{
- int irq = NO_IRQ_IGNORE;
+ /* -2 means ignore this interrupt */
+ int irq = -2;
#ifdef CONFIG_SMP
if (get_lppaca()->int_dword.fields.ipi_cnt) {
}
spin_unlock(&pending_irqs_lock);
if (irq >= NR_IRQS)
- irq = NO_IRQ_IGNORE;
+ irq = -2;
}
#endif
return irq;
}
-
-static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
-
- return 0;
-}
-
-static struct irq_host_ops iseries_irq_host_ops = {
- .map = iseries_irq_host_map,
-};
-
-/*
- * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
- * It must be called before the bus walk.
- */
-void __init iSeries_init_IRQ(void)
-{
- /* Register PCI event handler and open an event path */
- struct irq_host *host;
- int ret;
-
- /*
- * The Hypervisor only allows us up to 256 interrupt
- * sources (the irq number is passed in a u8).
- */
- irq_set_virq_count(256);
-
- /* Create irq host. No need for a revmap since HV will give us
- * back our virtual irq number
- */
- host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0);
- BUG_ON(host == NULL);
- irq_set_default_host(host);
-
- ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
- &pci_event_handler);
- if (ret == 0) {
- ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
- if (ret != 0)
- printk(KERN_ERR "iseries_init_IRQ: open event path "
- "failed with rc 0x%x\n", ret);
- } else
- printk(KERN_ERR "iseries_init_IRQ: register handler "
- "failed with rc 0x%x\n", ret);
-}
-