linux/arch/sparc64/kernel/pci_sun4v_asm.S
David S. Miller 35a17eb6a8 [SPARC64]: Add PCI MSI support on Niagara.
This is kind of hokey, we could use the hardware provided facilities
much better.

MSIs are assosciated with MSI Queues.  MSI Queues generate interrupts
when any MSI assosciated with it is signalled.  This suggests a
two-tiered IRQ dispatch scheme:

	MSI Queue interrupt --> queue interrupt handler
		MSI dispatch --> driver interrupt handler

But we just get one-level under Linux currently.  What I'd like to do
is possibly stick the IRQ actions into a per-MSI-Queue data structure,
and dispatch them form there, but the generic IRQ layer doesn't
provide a way to do that right now.

So, the current kludge is to "ACK" the interrupt by processing the
MSI Queue data structures and ACK'ing them, then we run the actual
handler like normal.

We are wasting a lot of useful information, for example the MSI data
and address are provided with ever MSI, as well as a system tick if
available.  If we could pass this into the IRQ handler it could help
with certain things, in particular for PCI-Express error messages.

The MSI entries on sparc64 also tell you exactly which bus/device/fn
sent the MSI, which would be great for error handling when no
registered IRQ handler can service the interrupt.

We override the disable/enable IRQ chip methods in sun4v_msi, so we
have to call {mask,unmask}_msi_irq() directly from there.  This is
another ugly wart.

Signed-off-by: David S. Miller <davem@davemloft.net>
2007-02-10 23:50:37 -08:00

362 lines
6.0 KiB
ArmAsm

/* pci_sun4v_asm: Hypervisor calls for PCI support.
*
* Copyright (C) 2006 David S. Miller <davem@davemloft.net>
*/
#include <asm/hypervisor.h>
/* %o0: devhandle
* %o1: tsbid
* %o2: num ttes
* %o3: io_attributes
* %o4: io_page_list phys address
*
* returns %o0: -status if status was non-zero, else
* %o0: num pages mapped
*/
.globl pci_sun4v_iommu_map
pci_sun4v_iommu_map:
mov %o5, %g1
mov HV_FAST_PCI_IOMMU_MAP, %o5
ta HV_FAST_TRAP
brnz,pn %o0, 1f
sub %g0, %o0, %o0
mov %o1, %o0
1: retl
nop
/* %o0: devhandle
* %o1: tsbid
* %o2: num ttes
*
* returns %o0: num ttes demapped
*/
.globl pci_sun4v_iommu_demap
pci_sun4v_iommu_demap:
mov HV_FAST_PCI_IOMMU_DEMAP, %o5
ta HV_FAST_TRAP
retl
mov %o1, %o0
/* %o0: devhandle
* %o1: tsbid
* %o2: &io_attributes
* %o3: &real_address
*
* returns %o0: status
*/
.globl pci_sun4v_iommu_getmap
pci_sun4v_iommu_getmap:
mov %o2, %o4
mov HV_FAST_PCI_IOMMU_GETMAP, %o5
ta HV_FAST_TRAP
stx %o1, [%o4]
stx %o2, [%o3]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: pci_device
* %o2: pci_config_offset
* %o3: size
*
* returns %o0: data
*
* If there is an error, the data will be returned
* as all 1's.
*/
.globl pci_sun4v_config_get
pci_sun4v_config_get:
mov HV_FAST_PCI_CONFIG_GET, %o5
ta HV_FAST_TRAP
brnz,a,pn %o1, 1f
mov -1, %o2
1: retl
mov %o2, %o0
/* %o0: devhandle
* %o1: pci_device
* %o2: pci_config_offset
* %o3: size
* %o4: data
*
* returns %o0: status
*
* status will be zero if the operation completed
* successfully, else -1 if not
*/
.globl pci_sun4v_config_put
pci_sun4v_config_put:
mov HV_FAST_PCI_CONFIG_PUT, %o5
ta HV_FAST_TRAP
brnz,a,pn %o1, 1f
mov -1, %o1
1: retl
mov %o1, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: msiq phys address
* %o3: num entries
*
* returns %o0: status
*
* status will be zero if the operation completed
* successfully, else -1 if not
*/
.globl pci_sun4v_msiq_conf
pci_sun4v_msiq_conf:
mov HV_FAST_PCI_MSIQ_CONF, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: &msiq_phys_addr
* %o3: &msiq_num_entries
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_info
pci_sun4v_msiq_info:
mov %o2, %o4
mov HV_FAST_PCI_MSIQ_INFO, %o5
ta HV_FAST_TRAP
stx %o1, [%o4]
stx %o2, [%o3]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: &valid
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_getvalid
pci_sun4v_msiq_getvalid:
mov HV_FAST_PCI_MSIQ_GETVALID, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: valid
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_setvalid
pci_sun4v_msiq_setvalid:
mov HV_FAST_PCI_MSIQ_SETVALID, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: &state
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_getstate
pci_sun4v_msiq_getstate:
mov HV_FAST_PCI_MSIQ_GETSTATE, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: state
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_setstate
pci_sun4v_msiq_setstate:
mov HV_FAST_PCI_MSIQ_SETSTATE, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: &head
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_gethead
pci_sun4v_msiq_gethead:
mov HV_FAST_PCI_MSIQ_GETHEAD, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: head
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_sethead
pci_sun4v_msiq_sethead:
mov HV_FAST_PCI_MSIQ_SETHEAD, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msiqid
* %o2: &tail
*
* returns %o0: status
*/
.globl pci_sun4v_msiq_gettail
pci_sun4v_msiq_gettail:
mov HV_FAST_PCI_MSIQ_GETTAIL, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: &valid
*
* returns %o0: status
*/
.globl pci_sun4v_msi_getvalid
pci_sun4v_msi_getvalid:
mov HV_FAST_PCI_MSI_GETVALID, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: valid
*
* returns %o0: status
*/
.globl pci_sun4v_msi_setvalid
pci_sun4v_msi_setvalid:
mov HV_FAST_PCI_MSI_SETVALID, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: &msiq
*
* returns %o0: status
*/
.globl pci_sun4v_msi_getmsiq
pci_sun4v_msi_getmsiq:
mov HV_FAST_PCI_MSI_GETMSIQ, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: msitype
* %o3: msiq
*
* returns %o0: status
*/
.globl pci_sun4v_msi_setmsiq
pci_sun4v_msi_setmsiq:
mov HV_FAST_PCI_MSI_SETMSIQ, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: &state
*
* returns %o0: status
*/
.globl pci_sun4v_msi_getstate
pci_sun4v_msi_getstate:
mov HV_FAST_PCI_MSI_GETSTATE, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: state
*
* returns %o0: status
*/
.globl pci_sun4v_msi_setstate
pci_sun4v_msi_setstate:
mov HV_FAST_PCI_MSI_SETSTATE, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: &msiq
*
* returns %o0: status
*/
.globl pci_sun4v_msg_getmsiq
pci_sun4v_msg_getmsiq:
mov HV_FAST_PCI_MSG_GETMSIQ, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: msiq
*
* returns %o0: status
*/
.globl pci_sun4v_msg_setmsiq
pci_sun4v_msg_setmsiq:
mov HV_FAST_PCI_MSG_SETMSIQ, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: &valid
*
* returns %o0: status
*/
.globl pci_sun4v_msg_getvalid
pci_sun4v_msg_getvalid:
mov HV_FAST_PCI_MSG_GETVALID, %o5
ta HV_FAST_TRAP
stx %o1, [%o2]
retl
mov %o0, %o0
/* %o0: devhandle
* %o1: msinum
* %o2: valid
*
* returns %o0: status
*/
.globl pci_sun4v_msg_setvalid
pci_sun4v_msg_setvalid:
mov HV_FAST_PCI_MSG_SETVALID, %o5
ta HV_FAST_TRAP
retl
mov %o0, %o0