提交 cb4cb2cb 编写于 作者: P Prarit Bhargava 提交者: Tony Luck

[IA64] hotplug/ia64: SN Hotplug Driver: SN IRQ Fixes

This patch  fixes the SN IRQ code such that cpu affinity and
Hotplug can modify IRQ values.  The sn_irq_info structures are now locked
using a RCU lock mechanism to avoid lock contention in the lost interrupt
WAR code.
Signed-off-by: NPrarit Bhargava <prarit@sgi.com>
Signed-off-by: NTony Luck <tony.luck@intel.com>
上级 bd53d127
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <asm/sn/simulator.h> #include <asm/sn/simulator.h>
#include <asm/sn/tioca_provider.h> #include <asm/sn/tioca_provider.h>
char master_baseio_wid;
nasid_t master_nasid = INVALID_NASID; /* Partition Master */ nasid_t master_nasid = INVALID_NASID; /* Partition Master */
struct slab_info { struct slab_info {
...@@ -231,11 +230,13 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) ...@@ -231,11 +230,13 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
{ {
int idx; int idx;
int segment = 0; int segment = 0;
uint64_t size;
struct sn_irq_info *sn_irq_info;
struct pci_dev *host_pci_dev;
int status = 0; int status = 0;
struct pcibus_bussoft *bs; struct pcibus_bussoft *bs;
struct pci_bus *host_pci_bus;
struct pci_dev *host_pci_dev;
struct sn_irq_info *sn_irq_info;
unsigned long size;
unsigned int bus_no, devfn;
dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
if (SN_PCIDEV_INFO(dev) <= 0) if (SN_PCIDEV_INFO(dev) <= 0)
...@@ -253,7 +254,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) ...@@ -253,7 +254,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
(u64) __pa(SN_PCIDEV_INFO(dev)), (u64) __pa(SN_PCIDEV_INFO(dev)),
(u64) __pa(sn_irq_info)); (u64) __pa(sn_irq_info));
if (status) if (status)
BUG(); /* Cannot get platform pci device information information */ BUG(); /* Cannot get platform pci device information */
/* Copy over PIO Mapped Addresses */ /* Copy over PIO Mapped Addresses */
for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
...@@ -275,15 +276,20 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) ...@@ -275,15 +276,20 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
dev->resource[idx].parent = &iomem_resource; dev->resource[idx].parent = &iomem_resource;
} }
/* set up host bus linkages */ /* Using the PROMs values for the PCI host bus, get the Linux
bs = SN_PCIBUS_BUSSOFT(dev->bus); * PCI host_pci_dev struct and set up host bus linkages
host_pci_dev = */
pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32,
SN_PCIDEV_INFO(dev)-> bus_no = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32;
pdi_slot_host_handle & 0xffffffff); devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff;
host_pci_bus = pci_find_bus(pci_domain_nr(dev->bus), bus_no);
host_pci_dev = pci_get_slot(host_pci_bus, devfn);
SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev;
SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info =
SN_PCIDEV_INFO(host_pci_dev); SN_PCIDEV_INFO(host_pci_dev);
SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev;
bs = SN_PCIBUS_BUSSOFT(dev->bus);
SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs; SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs;
if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
...@@ -297,6 +303,9 @@ static void sn_pci_fixup_slot(struct pci_dev *dev) ...@@ -297,6 +303,9 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info; SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info;
dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq; dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq;
sn_irq_fixup(dev, sn_irq_info); sn_irq_fixup(dev, sn_irq_info);
} else {
SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = NULL;
kfree(sn_irq_info);
} }
} }
...@@ -403,11 +412,7 @@ static int __init sn_pci_init(void) ...@@ -403,11 +412,7 @@ static int __init sn_pci_init(void)
*/ */
ia64_max_iommu_merge_mask = ~PAGE_MASK; ia64_max_iommu_merge_mask = ~PAGE_MASK;
sn_fixup_ionodes(); sn_fixup_ionodes();
sn_irq = kmalloc(sizeof(struct sn_irq_info *) * NR_IRQS, GFP_KERNEL); sn_irq_lh_init();
if (sn_irq <= 0)
BUG(); /* Canno afford to run out of memory. */
memset(sn_irq, 0, sizeof(struct sn_irq_info *) * NR_IRQS);
sn_init_cpei_timer(); sn_init_cpei_timer();
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
*/ */
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/spinlock.h>
#include <asm/sn/intr.h> #include <asm/sn/intr.h>
#include <asm/sn/addrs.h> #include <asm/sn/addrs.h>
#include <asm/sn/arch.h> #include <asm/sn/arch.h>
...@@ -25,7 +26,8 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info); ...@@ -25,7 +26,8 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
extern int sn_force_interrupt_flag; extern int sn_force_interrupt_flag;
extern int sn_ioif_inited; extern int sn_ioif_inited;
struct sn_irq_info **sn_irq; static struct list_head **sn_irq_lh;
static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget, static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget,
u64 sn_irq_info, u64 sn_irq_info,
...@@ -101,7 +103,7 @@ static void sn_end_irq(unsigned int irq) ...@@ -101,7 +103,7 @@ static void sn_end_irq(unsigned int irq)
nasid = get_nasid(); nasid = get_nasid();
event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR
(nasid, SH_EVENT_OCCURRED)); (nasid, SH_EVENT_OCCURRED));
/* If the UART bit is set here, we may have received an /* If the UART bit is set here, we may have received an
* interrupt from the UART that the driver missed. To * interrupt from the UART that the driver missed. To
* make sure, we IPI ourselves to force us to look again. * make sure, we IPI ourselves to force us to look again.
*/ */
...@@ -115,82 +117,84 @@ static void sn_end_irq(unsigned int irq) ...@@ -115,82 +117,84 @@ static void sn_end_irq(unsigned int irq)
force_interrupt(irq); force_interrupt(irq);
} }
static void sn_irq_info_free(struct rcu_head *head);
static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
{ {
struct sn_irq_info *sn_irq_info = sn_irq[irq]; struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
struct sn_irq_info *tmp_sn_irq_info;
int cpuid, cpuphys; int cpuid, cpuphys;
nasid_t t_nasid; /* nasid to target */
int t_slice; /* slice to target */
/* allocate a temp sn_irq_info struct to get new target info */
tmp_sn_irq_info = kmalloc(sizeof(*tmp_sn_irq_info), GFP_KERNEL);
if (!tmp_sn_irq_info)
return;
cpuid = first_cpu(mask); cpuid = first_cpu(mask);
cpuphys = cpu_physical_id(cpuid); cpuphys = cpu_physical_id(cpuid);
t_nasid = cpuid_to_nasid(cpuid);
t_slice = cpuid_to_slice(cpuid);
while (sn_irq_info) { list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
int status; sn_irq_lh[irq], list) {
int local_widget; uint64_t bridge;
uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge; int local_widget, status;
nasid_t local_nasid = NASID_GET(bridge); nasid_t local_nasid;
struct sn_irq_info *new_irq_info;
new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
if (new_irq_info == NULL)
break;
memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
bridge = (uint64_t) new_irq_info->irq_bridge;
if (!bridge) {
kfree(new_irq_info);
break; /* irq is not a device interrupt */
}
if (!bridge) local_nasid = NASID_GET(bridge);
break; /* irq is not a device interrupt */
if (local_nasid & 1) if (local_nasid & 1)
local_widget = TIO_SWIN_WIDGETNUM(bridge); local_widget = TIO_SWIN_WIDGETNUM(bridge);
else else
local_widget = SWIN_WIDGETNUM(bridge); local_widget = SWIN_WIDGETNUM(bridge);
/* Free the old PROM sn_irq_info structure */ /* Free the old PROM new_irq_info structure */
sn_intr_free(local_nasid, local_widget, sn_irq_info); sn_intr_free(local_nasid, local_widget, new_irq_info);
/* Update kernels new_irq_info with new target info */
unregister_intr_pda(new_irq_info);
/* allocate a new PROM sn_irq_info struct */ /* allocate a new PROM new_irq_info struct */
status = sn_intr_alloc(local_nasid, local_widget, status = sn_intr_alloc(local_nasid, local_widget,
__pa(tmp_sn_irq_info), irq, t_nasid, __pa(new_irq_info), irq,
t_slice); cpuid_to_nasid(cpuid),
cpuid_to_slice(cpuid));
if (status == 0) {
/* Update kernels sn_irq_info with new target info */ /* SAL call failed */
unregister_intr_pda(sn_irq_info); if (status) {
sn_irq_info->irq_cpuid = cpuid; kfree(new_irq_info);
sn_irq_info->irq_nasid = t_nasid; break;
sn_irq_info->irq_slice = t_slice; }
sn_irq_info->irq_xtalkaddr =
tmp_sn_irq_info->irq_xtalkaddr;
sn_irq_info->irq_cookie = tmp_sn_irq_info->irq_cookie;
register_intr_pda(sn_irq_info);
if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type)) {
pcibr_change_devices_irq(sn_irq_info);
}
sn_irq_info = sn_irq_info->irq_next; new_irq_info->irq_cpuid = cpuid;
register_intr_pda(new_irq_info);
if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type))
pcibr_change_devices_irq(new_irq_info);
spin_lock(&sn_irq_info_lock);
list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
spin_unlock(&sn_irq_info_lock);
call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
set_irq_affinity_info((irq & 0xff), cpuphys, 0); set_irq_affinity_info((irq & 0xff), cpuphys, 0);
#endif #endif
} else {
break; /* snp_affinity failed the intr_alloc */
}
} }
kfree(tmp_sn_irq_info);
} }
struct hw_interrupt_type irq_type_sn = { struct hw_interrupt_type irq_type_sn = {
"SN hub", .typename = "SN hub",
sn_startup_irq, .startup = sn_startup_irq,
sn_shutdown_irq, .shutdown = sn_shutdown_irq,
sn_enable_irq, .enable = sn_enable_irq,
sn_disable_irq, .disable = sn_disable_irq,
sn_ack_irq, .ack = sn_ack_irq,
sn_end_irq, .end = sn_end_irq,
sn_set_affinity_irq .set_affinity = sn_set_affinity_irq
}; };
unsigned int sn_local_vector_to_irq(u8 vector) unsigned int sn_local_vector_to_irq(u8 vector)
...@@ -231,19 +235,18 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) ...@@ -231,19 +235,18 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
struct sn_irq_info *tmp_irq_info; struct sn_irq_info *tmp_irq_info;
int i, foundmatch; int i, foundmatch;
rcu_read_lock();
if (pdacpu(cpu)->sn_last_irq == irq) { if (pdacpu(cpu)->sn_last_irq == irq) {
foundmatch = 0; foundmatch = 0;
for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--) { for (i = pdacpu(cpu)->sn_last_irq - 1;
tmp_irq_info = sn_irq[i]; i && !foundmatch; i--) {
while (tmp_irq_info) { list_for_each_entry_rcu(tmp_irq_info,
sn_irq_lh[i],
list) {
if (tmp_irq_info->irq_cpuid == cpu) { if (tmp_irq_info->irq_cpuid == cpu) {
foundmatch++; foundmatch = 1;
break; break;
} }
tmp_irq_info = tmp_irq_info->irq_next;
}
if (foundmatch) {
break;
} }
} }
pdacpu(cpu)->sn_last_irq = i; pdacpu(cpu)->sn_last_irq = i;
...@@ -251,60 +254,27 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) ...@@ -251,60 +254,27 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
if (pdacpu(cpu)->sn_first_irq == irq) { if (pdacpu(cpu)->sn_first_irq == irq) {
foundmatch = 0; foundmatch = 0;
for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++) { for (i = pdacpu(cpu)->sn_first_irq + 1;
tmp_irq_info = sn_irq[i]; i < NR_IRQS && !foundmatch; i++) {
while (tmp_irq_info) { list_for_each_entry_rcu(tmp_irq_info,
sn_irq_lh[i],
list) {
if (tmp_irq_info->irq_cpuid == cpu) { if (tmp_irq_info->irq_cpuid == cpu) {
foundmatch++; foundmatch = 1;
break; break;
} }
tmp_irq_info = tmp_irq_info->irq_next;
}
if (foundmatch) {
break;
} }
} }
pdacpu(cpu)->sn_first_irq = ((i == NR_IRQS) ? 0 : i); pdacpu(cpu)->sn_first_irq = ((i == NR_IRQS) ? 0 : i);
} }
rcu_read_unlock();
} }
struct sn_irq_info *sn_irq_alloc(nasid_t local_nasid, int local_widget, int irq, static void sn_irq_info_free(struct rcu_head *head)
nasid_t nasid, int slice)
{ {
struct sn_irq_info *sn_irq_info; struct sn_irq_info *sn_irq_info;
int status;
sn_irq_info = kmalloc(sizeof(*sn_irq_info), GFP_KERNEL);
if (sn_irq_info == NULL)
return NULL;
memset(sn_irq_info, 0x0, sizeof(*sn_irq_info));
status =
sn_intr_alloc(local_nasid, local_widget, __pa(sn_irq_info), irq,
nasid, slice);
if (status) {
kfree(sn_irq_info);
return NULL;
} else {
return sn_irq_info;
}
}
void sn_irq_free(struct sn_irq_info *sn_irq_info)
{
uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
nasid_t local_nasid = NASID_GET(bridge);
int local_widget;
if (local_nasid & 1) /* tio check */
local_widget = TIO_SWIN_WIDGETNUM(bridge);
else
local_widget = SWIN_WIDGETNUM(bridge);
sn_intr_free(local_nasid, local_widget, sn_irq_info);
sn_irq_info = container_of(head, struct sn_irq_info, rcu);
kfree(sn_irq_info); kfree(sn_irq_info);
} }
...@@ -314,30 +284,54 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) ...@@ -314,30 +284,54 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
int slice = sn_irq_info->irq_slice; int slice = sn_irq_info->irq_slice;
int cpu = nasid_slice_to_cpuid(nasid, slice); int cpu = nasid_slice_to_cpuid(nasid, slice);
pci_dev_get(pci_dev);
sn_irq_info->irq_cpuid = cpu; sn_irq_info->irq_cpuid = cpu;
sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev); sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev);
/* link it into the sn_irq[irq] list */ /* link it into the sn_irq[irq] list */
sn_irq_info->irq_next = sn_irq[sn_irq_info->irq_irq]; spin_lock(&sn_irq_info_lock);
sn_irq[sn_irq_info->irq_irq] = sn_irq_info; list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
spin_unlock(&sn_irq_info_lock);
(void)register_intr_pda(sn_irq_info); (void)register_intr_pda(sn_irq_info);
} }
void sn_irq_unfixup(struct pci_dev *pci_dev)
{
struct sn_irq_info *sn_irq_info;
/* Only cleanup IRQ stuff if this device has a host bus context */
if (!SN_PCIDEV_BUSSOFT(pci_dev))
return;
sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info;
if (!sn_irq_info || !sn_irq_info->irq_irq)
return;
unregister_intr_pda(sn_irq_info);
spin_lock(&sn_irq_info_lock);
list_del_rcu(&sn_irq_info->list);
spin_unlock(&sn_irq_info_lock);
call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
pci_dev_put(pci_dev);
}
static void force_interrupt(int irq) static void force_interrupt(int irq)
{ {
struct sn_irq_info *sn_irq_info; struct sn_irq_info *sn_irq_info;
if (!sn_ioif_inited) if (!sn_ioif_inited)
return; return;
sn_irq_info = sn_irq[irq];
while (sn_irq_info) { rcu_read_lock();
list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) {
if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
(sn_irq_info->irq_bridge != NULL)) { (sn_irq_info->irq_bridge != NULL))
pcibr_force_interrupt(sn_irq_info); pcibr_force_interrupt(sn_irq_info);
}
sn_irq_info = sn_irq_info->irq_next;
} }
rcu_read_unlock();
} }
/* /*
...@@ -402,19 +396,41 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) ...@@ -402,19 +396,41 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
void sn_lb_int_war_check(void) void sn_lb_int_war_check(void)
{ {
struct sn_irq_info *sn_irq_info;
int i; int i;
if (!sn_ioif_inited || pda->sn_first_irq == 0) if (!sn_ioif_inited || pda->sn_first_irq == 0)
return; return;
rcu_read_lock();
for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) { for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
struct sn_irq_info *sn_irq_info = sn_irq[i]; list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) {
while (sn_irq_info) { /*
/* Only call for PCI bridges that are fully initialized. */ * Only call for PCI bridges that are fully
* initialized.
*/
if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
(sn_irq_info->irq_bridge != NULL)) { (sn_irq_info->irq_bridge != NULL))
sn_check_intr(i, sn_irq_info); sn_check_intr(i, sn_irq_info);
}
sn_irq_info = sn_irq_info->irq_next;
} }
} }
rcu_read_unlock();
}
void sn_irq_lh_init(void)
{
int i;
sn_irq_lh = kmalloc(sizeof(struct list_head *) * NR_IRQS, GFP_KERNEL);
if (!sn_irq_lh)
panic("SN PCI INIT: Failed to allocate memory for PCI init\n");
for (i = 0; i < NR_IRQS; i++) {
sn_irq_lh[i] = kmalloc(sizeof(struct list_head), GFP_KERNEL);
if (!sn_irq_lh[i])
panic("SN PCI INIT: Failed IRQ memory allocation\n");
INIT_LIST_HEAD(sn_irq_lh[i]);
}
} }
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#ifndef _ASM_IA64_SN_INTR_H #ifndef _ASM_IA64_SN_INTR_H
#define _ASM_IA64_SN_INTR_H #define _ASM_IA64_SN_INTR_H
#include <linux/rcupdate.h>
#define SGI_UART_VECTOR (0xe9) #define SGI_UART_VECTOR (0xe9)
#define SGI_PCIBR_ERROR (0x33) #define SGI_PCIBR_ERROR (0x33)
...@@ -33,7 +35,7 @@ ...@@ -33,7 +35,7 @@
// The SN PROM irq struct // The SN PROM irq struct
struct sn_irq_info { struct sn_irq_info {
struct sn_irq_info *irq_next; /* sharing irq list */ struct sn_irq_info *irq_next; /* deprecated DO NOT USE */
short irq_nasid; /* Nasid IRQ is assigned to */ short irq_nasid; /* Nasid IRQ is assigned to */
int irq_slice; /* slice IRQ is assigned to */ int irq_slice; /* slice IRQ is assigned to */
int irq_cpuid; /* kernel logical cpuid */ int irq_cpuid; /* kernel logical cpuid */
...@@ -47,6 +49,8 @@ struct sn_irq_info { ...@@ -47,6 +49,8 @@ struct sn_irq_info {
int irq_cookie; /* unique cookie */ int irq_cookie; /* unique cookie */
int irq_flags; /* flags */ int irq_flags; /* flags */
int irq_share_cnt; /* num devices sharing IRQ */ int irq_share_cnt; /* num devices sharing IRQ */
struct list_head list; /* list of sn_irq_info structs */
struct rcu_head rcu; /* rcu callback list */
}; };
extern void sn_send_IPI_phys(int, long, int, int); extern void sn_send_IPI_phys(int, long, int, int);
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include <linux/pci.h> #include <linux/pci.h>
extern struct sn_irq_info **sn_irq;
#define SN_PCIDEV_INFO(pci_dev) \ #define SN_PCIDEV_INFO(pci_dev) \
((struct pcidev_info *)(pci_dev)->sysdata) ((struct pcidev_info *)(pci_dev)->sysdata)
...@@ -50,9 +48,11 @@ struct pcidev_info { ...@@ -50,9 +48,11 @@ struct pcidev_info {
struct sn_irq_info *pdi_sn_irq_info; struct sn_irq_info *pdi_sn_irq_info;
struct sn_pcibus_provider *pdi_provider; /* sn pci ops */ struct sn_pcibus_provider *pdi_provider; /* sn pci ops */
struct pci_dev *host_pci_dev; /* host bus link */
}; };
extern void sn_irq_fixup(struct pci_dev *pci_dev, extern void sn_irq_fixup(struct pci_dev *pci_dev,
struct sn_irq_info *sn_irq_info); struct sn_irq_info *sn_irq_info);
extern void sn_irq_lh_init(void);
#endif /* _ASM_IA64_SN_PCI_PCIDEV_H */ #endif /* _ASM_IA64_SN_PCI_PCIDEV_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册