**
** PA Firmware
** -----------
-** PA-RISC platforms have two fundementally different types of firmware.
+** PA-RISC platforms have two fundamentally different types of firmware.
** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
** and BARs similar to a traditional PC BIOS.
** The newer "PAT" firmware supports PDC calls which return tables.
-** PAT firmware only initializes PCI Console and Boot interface.
-** With these tables, the OS can progam all other PCI devices.
+** PAT firmware only initializes the PCI Console and Boot interface.
+** With these tables, the OS can program all other PCI devices.
**
** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
#include <asm/superio.h>
#endif
-#include <asm/iosapic.h>
+#include <asm/ropes.h>
#include "./iosapic_private.h"
#define MODULE_NAME "iosapic"
#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
-static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(iosapic_lock);
static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
{
* 4-byte alignment on 32-bit kernels
*/
a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
- a = (a + 7) & ~7;
+ a = (a + 7UL) & ~7UL;
return (struct irt_entry *)a;
}
static struct vector_info *iosapic_get_vector(unsigned int irq)
{
- return irq_desc[irq].handler_data;
+ return irq_desc[irq].chip_data;
}
static void iosapic_disable_irq(unsigned int irq)
DBG(KERN_DEBUG "end_irq(%d): eoi(%p, 0x%x)\n", irq,
vi->eoi_addr, vi->eoi_data);
iosapic_eoi(vi->eoi_addr, vi->eoi_data);
+ cpu_end_irq(irq);
}
static unsigned int iosapic_startup_irq(unsigned int irq)
return 0;
}
+#ifdef CONFIG_SMP
+static void iosapic_set_affinity_irq(unsigned int irq, cpumask_t dest)
+{
+ struct vector_info *vi = iosapic_get_vector(irq);
+ u32 d0, d1, dummy_d0;
+ unsigned long flags;
+
+ if (cpu_check_affinity(irq, &dest))
+ return;
+
+ vi->txn_addr = txn_affinity_addr(irq, first_cpu(dest));
+
+ spin_lock_irqsave(&iosapic_lock, flags);
+ /* d1 contains the destination CPU, so only want to set that
+ * entry */
+ iosapic_rd_irt_entry(vi, &d0, &d1);
+ iosapic_set_irt_data(vi, &dummy_d0, &d1);
+ iosapic_wr_irt_entry(vi, d0, d1);
+ spin_unlock_irqrestore(&iosapic_lock, flags);
+}
+#endif
+
static struct hw_interrupt_type iosapic_interrupt_type = {
.typename = "IO-SAPIC-level",
.startup = iosapic_startup_irq,
.shutdown = iosapic_disable_irq,
.enable = iosapic_enable_irq,
.disable = iosapic_disable_irq,
- .ack = no_ack_irq,
+ .ack = cpu_ack_irq,
.end = iosapic_end_irq,
-// .set_affinity = iosapic_set_affinity_irq,
+#ifdef CONFIG_SMP
+ .set_affinity = iosapic_set_affinity_irq,
+#endif
};
int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
return NULL;
}
- isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+ isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
if (!isi) {
BUG();
return NULL;
}
- memset(isi, 0, sizeof(struct iosapic_info));
-
- isi->addr = ioremap(hpa, 4096);
+ isi->addr = ioremap_nocache(hpa, 4096);
isi->isi_hpa = hpa;
isi->isi_version = iosapic_rd_version(isi);
isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
vip = isi->isi_vector = (struct vector_info *)
- kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
+ kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
if (vip == NULL) {
kfree(isi);
return NULL;
}
- memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
-
for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
vip->irqline = (unsigned char) cnt;
vip->iosapic = isi;