2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
9 #include <linux/types.h>
10 #include <linux/pci.h>
11 #include <linux/cpumask.h>
13 #include <asm/sn/addrs.h>
14 #include <asm/sn/intr.h>
15 #include <asm/sn/pcibus_provider_defs.h>
16 #include <asm/sn/pcidev.h>
17 #include <asm/sn/nodepda.h>
23 struct sn_irq_info
*sn_irq_info
;
26 static struct sn_msi_info
*sn_msi_info
;
29 sn_msi_teardown(unsigned int vector
)
34 struct pcidev_info
*sn_pdev
;
35 struct sn_irq_info
*sn_irq_info
;
36 struct pcibus_bussoft
*bussoft
;
37 struct sn_pcibus_provider
*provider
;
39 sn_irq_info
= sn_msi_info
[vector
].sn_irq_info
;
40 if (sn_irq_info
== NULL
|| sn_irq_info
->irq_int_bit
>= 0)
43 sn_pdev
= (struct pcidev_info
*)sn_irq_info
->irq_pciioinfo
;
44 pdev
= sn_pdev
->pdi_linux_pcidev
;
45 provider
= SN_PCIDEV_BUSPROVIDER(pdev
);
47 (*provider
->dma_unmap
)(pdev
,
48 sn_msi_info
[vector
].pci_addr
,
50 sn_msi_info
[vector
].pci_addr
= 0;
52 bussoft
= SN_PCIDEV_BUSSOFT(pdev
);
53 nasid
= NASID_GET(bussoft
->bs_base
);
54 widget
= (nasid
& 1) ?
55 TIO_SWIN_WIDGETNUM(bussoft
->bs_base
) :
56 SWIN_WIDGETNUM(bussoft
->bs_base
);
58 sn_intr_free(nasid
, widget
, sn_irq_info
);
59 sn_msi_info
[vector
].sn_irq_info
= NULL
;
65 sn_msi_setup(struct pci_dev
*pdev
, unsigned int vector
,
66 u32
*addr_hi
, u32
*addr_lo
, u32
*data
)
72 struct sn_irq_info
*sn_irq_info
;
73 struct pcibus_bussoft
*bussoft
= SN_PCIDEV_BUSSOFT(pdev
);
74 struct sn_pcibus_provider
*provider
= SN_PCIDEV_BUSPROVIDER(pdev
);
79 if (provider
== NULL
|| provider
->dma_map_consistent
== NULL
)
83 * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
84 * decide which cpu to direct this msi at by default.
87 nasid
= NASID_GET(bussoft
->bs_base
);
88 widget
= (nasid
& 1) ?
89 TIO_SWIN_WIDGETNUM(bussoft
->bs_base
) :
90 SWIN_WIDGETNUM(bussoft
->bs_base
);
92 sn_irq_info
= kzalloc(sizeof(struct sn_irq_info
), GFP_KERNEL
);
96 status
= sn_intr_alloc(nasid
, widget
, sn_irq_info
, vector
, -1, -1);
102 sn_irq_info
->irq_int_bit
= -1; /* mark this as an MSI irq */
103 sn_irq_fixup(pdev
, sn_irq_info
);
105 /* Prom probably should fill these in, but doesn't ... */
106 sn_irq_info
->irq_bridge_type
= bussoft
->bs_asic_type
;
107 sn_irq_info
->irq_bridge
= (void *)bussoft
->bs_base
;
110 * Map the xio address into bus space
112 bus_addr
= (*provider
->dma_map_consistent
)(pdev
,
113 sn_irq_info
->irq_xtalkaddr
,
114 sizeof(sn_irq_info
->irq_xtalkaddr
),
115 SN_DMA_MSI
|SN_DMA_ADDR_XIO
);
117 sn_intr_free(nasid
, widget
, sn_irq_info
);
122 sn_msi_info
[vector
].sn_irq_info
= sn_irq_info
;
123 sn_msi_info
[vector
].pci_addr
= bus_addr
;
125 *addr_hi
= (u32
)(bus_addr
>> 32);
126 *addr_lo
= (u32
)(bus_addr
& 0x00000000ffffffff);
129 * In the SN platform, bit 16 is a "send vector" bit which
130 * must be present in order to move the vector through the system.
132 *data
= 0x100 + (unsigned int)vector
;
135 set_irq_affinity_info((vector
& 0xff), sn_irq_info
->irq_cpuid
, 0);
142 sn_msi_target(unsigned int vector
, unsigned int cpu
,
143 u32
*addr_hi
, u32
*addr_lo
)
148 struct pci_dev
*pdev
;
149 struct pcidev_info
*sn_pdev
;
150 struct sn_irq_info
*sn_irq_info
;
151 struct sn_irq_info
*new_irq_info
;
152 struct sn_pcibus_provider
*provider
;
154 sn_irq_info
= sn_msi_info
[vector
].sn_irq_info
;
155 if (sn_irq_info
== NULL
|| sn_irq_info
->irq_int_bit
>= 0)
159 * Release XIO resources for the old MSI PCI address
162 sn_pdev
= (struct pcidev_info
*)sn_irq_info
->irq_pciioinfo
;
163 pdev
= sn_pdev
->pdi_linux_pcidev
;
164 provider
= SN_PCIDEV_BUSPROVIDER(pdev
);
166 bus_addr
= (u64
)(*addr_hi
) << 32 | (u64
)(*addr_lo
);
167 (*provider
->dma_unmap
)(pdev
, bus_addr
, PCI_DMA_FROMDEVICE
);
168 sn_msi_info
[vector
].pci_addr
= 0;
170 nasid
= cpuid_to_nasid(cpu
);
171 slice
= cpuid_to_slice(cpu
);
173 new_irq_info
= sn_retarget_vector(sn_irq_info
, nasid
, slice
);
174 sn_msi_info
[vector
].sn_irq_info
= new_irq_info
;
175 if (new_irq_info
== NULL
)
179 * Map the xio address into bus space
182 bus_addr
= (*provider
->dma_map_consistent
)(pdev
,
183 new_irq_info
->irq_xtalkaddr
,
184 sizeof(new_irq_info
->irq_xtalkaddr
),
185 SN_DMA_MSI
|SN_DMA_ADDR_XIO
);
187 sn_msi_info
[vector
].pci_addr
= bus_addr
;
188 *addr_hi
= (u32
)(bus_addr
>> 32);
189 *addr_lo
= (u32
)(bus_addr
& 0x00000000ffffffff);
192 struct msi_ops sn_msi_ops
= {
193 .setup
= sn_msi_setup
,
194 .teardown
= sn_msi_teardown
,
196 .target
= sn_msi_target
,
204 kzalloc(sizeof(struct sn_msi_info
) * NR_VECTORS
, GFP_KERNEL
);
208 msi_register(&sn_msi_ops
);