Commit f35f8a3b authored by Jesse Barnes's avatar Jesse Barnes Committed by David Mosberger

[PATCH] ia64: machine vectors for readX routines

We need readX() to be machine vectors since some platforms don't provide
DMA coherence via PIO reads (PCI drivers and the spec imply that this is
a good idea).  Writes are ok though for all existing ia64 platforms (and
hopefully it'll stay that way).
parent ac102a4f
...@@ -87,12 +87,31 @@ ia64_outl (unsigned int val, unsigned long port) ...@@ -87,12 +87,31 @@ ia64_outl (unsigned int val, unsigned long port)
__ia64_outl(val, port); __ia64_outl(val, port);
} }
void unsigned char
ia64_mmiob (void) ia64_readb (void *addr)
{
return __ia64_readb (addr);
}
unsigned short
ia64_readw (void *addr)
{ {
__ia64_mmiob(); return __ia64_readw (addr);
} }
unsigned int
ia64_readl (void *addr)
{
return __ia64_readl (addr);
}
unsigned long
ia64_readq (void *addr)
{
return __ia64_readq (addr)
}
/* define aliases: */ /* define aliases: */
asm (".global __ia64_inb, __ia64_inw, __ia64_inl"); asm (".global __ia64_inb, __ia64_inw, __ia64_inl");
...@@ -105,7 +124,11 @@ asm ("__ia64_outb = ia64_outb"); ...@@ -105,7 +124,11 @@ asm ("__ia64_outb = ia64_outb");
asm ("__ia64_outw = ia64_outw"); asm ("__ia64_outw = ia64_outw");
asm ("__ia64_outl = ia64_outl"); asm ("__ia64_outl = ia64_outl");
asm (".global __ia64_mmiob"); asm (".global __ia64_readb, __ia64_readw, __ia64_readl, __ia64_readq");
asm ("__ia64_mmiob = ia64_mmiob"); asm ("__ia64_readb = ia64_readb");
asm ("__ia64_readw = ia64_readw");
asm ("__ia64_readl = ia64_readl");
asm ("__ia64_readq = ia64_readq");
#endif /* CONFIG_IA64_GENERIC */ #endif /* CONFIG_IA64_GENERIC */
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2003 Silicon Graphics, Inc. All rights reserved.
*
* The generic kernel requires function pointers to these routines, so
* we wrap the inlines from asm/ia64/sn/sn2/io.h here.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <asm/sn/sn2/io.h>
#ifdef CONFIG_IA64_GENERIC
unsigned int
sn_inb (unsigned long port)
{
return __sn_inb(port);
}
unsigned int
sn_inw (unsigned long port)
{
return __sn_inw(port);
}
unsigned int
sn_inl (unsigned long port)
{
return __sn_inl(port);
}
void
sn_outb (unsigned char val, unsigned long port)
{
__sn_outb(val, port);
}
void
sn_outw (unsigned short val, unsigned long port)
{
__sn_outw(val, port);
}
void
sn_outl (unsigned int val, unsigned long port)
{
__sn_outl(val, port);
}
unsigned char
sn_readb (void *addr)
{
return __sn_readb (addr);
}
unsigned short
sn_readw (void *addr)
{
return __sn_readw (addr);
}
unsigned int
sn_readl (void *addr)
{
return __sn_readl (addr);
}
unsigned long
sn_readq (void *addr)
{
return __sn_readq (addr)
}
/* define aliases: */
asm (".global __sn_inb, __sn_inw, __sn_inl");
asm ("__sn_inb = sn_inb");
asm ("__sn_inw = sn_inw");
asm ("__sn_inl = sn_inl");
asm (".global __sn_outb, __sn_outw, __sn_outl");
asm ("__sn_outb = sn_outb");
asm ("__sn_outw = sn_outw");
asm ("__sn_outl = sn_outl");
asm (".global __sn_readb, __sn_readw, __sn_readl, __sn_readq");
asm ("__sn_readb = sn_readb");
asm ("__sn_readw = sn_readw");
asm ("__sn_readl = sn_readl");
asm ("__sn_readq = sn_readq");
#endif /* CONFIG_IA64_GENERIC */
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
* *
* Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/ */
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/module.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/sn/simulator.h> #include <asm/sn/simulator.h>
...@@ -46,8 +47,10 @@ sn_io_addr(unsigned long port) ...@@ -46,8 +47,10 @@ sn_io_addr(unsigned long port)
} }
} }
EXPORT_SYMBOL(sn_io_addr);
/** /**
* sn2_mmiob - I/O space memory barrier * sn_mmiob - I/O space memory barrier
* *
* Acts as a memory mapped I/O barrier for platforms that queue writes to * Acts as a memory mapped I/O barrier for platforms that queue writes to
* I/O space. This ensures that subsequent writes to I/O space arrive after * I/O space. This ensures that subsequent writes to I/O space arrive after
...@@ -60,9 +63,9 @@ sn_io_addr(unsigned long port) ...@@ -60,9 +63,9 @@ sn_io_addr(unsigned long port)
* *
*/ */
void void
sn2_mmiob (void) sn_mmiob (void)
{ {
while ((((volatile unsigned long) (*pda->pio_write_status_addr)) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) != while ((((volatile unsigned long) (*pda.pio_write_status_addr)) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) !=
SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK)
udelay(1); udelay(1);
} }
...@@ -287,27 +287,32 @@ __outsl (unsigned long port, void *src, unsigned long count) ...@@ -287,27 +287,32 @@ __outsl (unsigned long port, void *src, unsigned long count)
/* /*
* The address passed to these functions are ioremap()ped already. * The address passed to these functions are ioremap()ped already.
*
* We need these to be machine vectors since some platforms don't provide
* DMA coherence via PIO reads (PCI drivers and the spec imply that this is
* a good idea). Writes are ok though for all existing ia64 platforms (and
* hopefully it'll stay that way).
*/ */
static inline unsigned char static inline unsigned char
__readb (void *addr) __ia64_readb (void *addr)
{ {
return *(volatile unsigned char *)addr; return *(volatile unsigned char *)addr;
} }
static inline unsigned short static inline unsigned short
__readw (void *addr) __ia64_readw (void *addr)
{ {
return *(volatile unsigned short *)addr; return *(volatile unsigned short *)addr;
} }
static inline unsigned int static inline unsigned int
__readl (void *addr) __ia64_readl (void *addr)
{ {
return *(volatile unsigned int *) addr; return *(volatile unsigned int *) addr;
} }
static inline unsigned long static inline unsigned long
__readq (void *addr) __ia64_readq (void *addr)
{ {
return *(volatile unsigned long *) addr; return *(volatile unsigned long *) addr;
} }
...@@ -336,6 +341,11 @@ __writeq (unsigned long val, void *addr) ...@@ -336,6 +341,11 @@ __writeq (unsigned long val, void *addr)
*(volatile unsigned long *) addr = val; *(volatile unsigned long *) addr = val;
} }
#define __readb platform_readb
#define __readw platform_readw
#define __readl platform_readl
#define __readq platform_readq
#define readb(a) __readb((void *)(a)) #define readb(a) __readb((void *)(a))
#define readw(a) __readw((void *)(a)) #define readw(a) __readw((void *)(a))
#define readl(a) __readl((void *)(a)) #define readl(a) __readl((void *)(a))
......
...@@ -61,6 +61,10 @@ typedef unsigned int ia64_mv_inl_t (unsigned long); ...@@ -61,6 +61,10 @@ typedef unsigned int ia64_mv_inl_t (unsigned long);
typedef void ia64_mv_outb_t (unsigned char, unsigned long); typedef void ia64_mv_outb_t (unsigned char, unsigned long);
typedef void ia64_mv_outw_t (unsigned short, unsigned long); typedef void ia64_mv_outw_t (unsigned short, unsigned long);
typedef void ia64_mv_outl_t (unsigned int, unsigned long); typedef void ia64_mv_outl_t (unsigned int, unsigned long);
typedef unsigned char ia64_mv_readb_t (void *);
typedef unsigned short ia64_mv_readw_t (void *);
typedef unsigned int ia64_mv_readl_t (void *);
typedef unsigned long ia64_mv_readq_t (void *);
extern void machvec_noop (void); extern void machvec_noop (void);
...@@ -109,6 +113,10 @@ extern void machvec_noop (void); ...@@ -109,6 +113,10 @@ extern void machvec_noop (void);
# define platform_outb ia64_mv.outb # define platform_outb ia64_mv.outb
# define platform_outw ia64_mv.outw # define platform_outw ia64_mv.outw
# define platform_outl ia64_mv.outl # define platform_outl ia64_mv.outl
# define platform_readb ia64_mv.readb
# define platform_readw ia64_mv.readw
# define platform_readl ia64_mv.readl
# define platform_readq ia64_mv.readq
# endif # endif
/* __attribute__((__aligned__(16))) is required to make size of the /* __attribute__((__aligned__(16))) is required to make size of the
...@@ -147,7 +155,11 @@ struct ia64_machine_vector { ...@@ -147,7 +155,11 @@ struct ia64_machine_vector {
ia64_mv_outb_t *outb; ia64_mv_outb_t *outb;
ia64_mv_outw_t *outw; ia64_mv_outw_t *outw;
ia64_mv_outl_t *outl; ia64_mv_outl_t *outl;
} __attribute__((__aligned__(16))); ia64_mv_readb_t *readb;
ia64_mv_readw_t *readw;
ia64_mv_readl_t *readl;
ia64_mv_readq_t *readq;
};
#define MACHVEC_INIT(name) \ #define MACHVEC_INIT(name) \
{ \ { \
...@@ -181,6 +193,10 @@ struct ia64_machine_vector { ...@@ -181,6 +193,10 @@ struct ia64_machine_vector {
platform_outb, \ platform_outb, \
platform_outw, \ platform_outw, \
platform_outl, \ platform_outl, \
platform_readb, \
platform_readw, \
platform_readl, \
platform_readq, \
} }
extern struct ia64_machine_vector ia64_mv; extern struct ia64_machine_vector ia64_mv;
...@@ -296,5 +312,17 @@ extern ia64_mv_pci_dma_supported swiotlb_pci_dma_supported; ...@@ -296,5 +312,17 @@ extern ia64_mv_pci_dma_supported swiotlb_pci_dma_supported;
#ifndef platform_outl #ifndef platform_outl
# define platform_outl __ia64_outl # define platform_outl __ia64_outl
#endif #endif
#ifndef platform_readb
# define platform_readb __ia64_readb
#endif
#ifndef platform_readw
# define platform_readw __ia64_readw
#endif
#ifndef platform_readl
# define platform_readl __ia64_readl
#endif
#ifndef platform_readq
# define platform_readq __ia64_readq
#endif
#endif /* _ASM_IA64_MACHVEC_H */ #endif /* _ASM_IA64_MACHVEC_H */
/* /*
* Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. * Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License * under the terms of version 2 of the GNU General Public License
...@@ -41,12 +41,16 @@ extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge; ...@@ -41,12 +41,16 @@ extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge;
extern ia64_mv_irq_desc sn_irq_desc; extern ia64_mv_irq_desc sn_irq_desc;
extern ia64_mv_irq_to_vector sn_irq_to_vector; extern ia64_mv_irq_to_vector sn_irq_to_vector;
extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq; extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
extern ia64_mv_inb_t sn_inb; extern ia64_mv_inb_t __sn_inb;
extern ia64_mv_inw_t sn_inw; extern ia64_mv_inw_t __sn_inw;
extern ia64_mv_inl_t sn_inl; extern ia64_mv_inl_t __sn_inl;
extern ia64_mv_outb_t sn_outb; extern ia64_mv_outb_t __sn_outb;
extern ia64_mv_outw_t sn_outw; extern ia64_mv_outw_t __sn_outw;
extern ia64_mv_outl_t sn_outl; extern ia64_mv_outl_t __sn_outl;
extern ia64_mv_readb_t __sn_readb;
extern ia64_mv_readw_t __sn_readw;
extern ia64_mv_readl_t __sn_readl;
extern ia64_mv_readq_t __sn_readq;
extern ia64_mv_pci_alloc_consistent sn_pci_alloc_consistent; extern ia64_mv_pci_alloc_consistent sn_pci_alloc_consistent;
extern ia64_mv_pci_free_consistent sn_pci_free_consistent; extern ia64_mv_pci_free_consistent sn_pci_free_consistent;
extern ia64_mv_pci_map_single sn_pci_map_single; extern ia64_mv_pci_map_single sn_pci_map_single;
...@@ -71,12 +75,17 @@ extern ia64_mv_pci_dma_supported sn_pci_dma_supported; ...@@ -71,12 +75,17 @@ extern ia64_mv_pci_dma_supported sn_pci_dma_supported;
#define platform_irq_init sn_irq_init #define platform_irq_init sn_irq_init
#define platform_send_ipi sn2_send_IPI #define platform_send_ipi sn2_send_IPI
#define platform_global_tlb_purge sn2_global_tlb_purge #define platform_global_tlb_purge sn2_global_tlb_purge
#define platform_inb sn_inb #define platform_pci_fixup sn_pci_fixup
#define platform_inw sn_inw #define platform_inb __sn_inb
#define platform_inl sn_inl #define platform_inw __sn_inw
#define platform_outb sn_outb #define platform_inl __sn_inl
#define platform_outw sn_outw #define platform_outb __sn_outb
#define platform_outl sn_outl #define platform_outw __sn_outw
#define platform_outl __sn_outl
#define platform_readb __sn_readb
#define platform_readw __sn_readw
#define platform_readl __sn_readl
#define platform_readq __sn_readq
#define platform_irq_desc sn_irq_desc #define platform_irq_desc sn_irq_desc
#define platform_irq_to_vector sn_irq_to_vector #define platform_irq_to_vector sn_irq_to_vector
#define platform_local_vector_to_irq sn_local_vector_to_irq #define platform_local_vector_to_irq sn_local_vector_to_irq
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
* *
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (C) 2000 Ralf Baechle * Copyright (C) 2000 Ralf Baechle
* Copyright (C) 2000-2001 Silicon Graphics, Inc.
*/ */
#ifndef _ASM_IA64_SN_IO_H #ifndef _ASM_IA64_SN_IO_H
#define _ASM_IA64_SN_IO_H #define _ASM_IA64_SN_IO_H
...@@ -78,4 +78,9 @@ ...@@ -78,4 +78,9 @@
#include <asm/sn/sn2/shubio.h> #include <asm/sn/sn2/shubio.h>
#endif #endif
/*
* Used to ensure write ordering (like mb(), but for I/O space)
*/
extern void sn_mmiob(void);
#endif /* _ASM_IA64_SN_IO_H */ #endif /* _ASM_IA64_SN_IO_H */
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_SN_SN2_IO_H
#define _ASM_SN_SN2_IO_H
extern void * sn_io_addr(unsigned long port); /* Forward definition */
extern void sn_mmiob(void); /* Forward definition */
#define __sn_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory")
extern void sn_dma_flush(unsigned long);
/*
* The following routines are SN Platform specific, called when
* a reference is made to inX/outX set macros. SN Platform
* inX set of macros ensures that Posted DMA writes on the
* Bridge is flushed.
*
* The routines should be self explainatory.
*/
static inline unsigned int
__sn_inb (unsigned long port)
{
volatile unsigned char *addr = sn_io_addr(port);
unsigned char ret;
ret = *addr;
sn_dma_flush((unsigned long)addr);
__sn_mf_a();
return ret;
}
static inline unsigned int
__sn_inw (unsigned long port)
{
volatile unsigned short *addr = sn_io_addr(port);
unsigned short ret;
ret = *addr;
sn_dma_flush((unsigned long)addr);
__sn_mf_a();
return ret;
}
static inline unsigned int
__sn_inl (unsigned long port)
{
volatile unsigned int *addr = sn_io_addr(port);
unsigned int ret;
ret = *addr;
sn_dma_flush((unsigned long)addr);
__sn_mf_a();
return ret;
}
static inline void
__sn_outb (unsigned char val, unsigned long port)
{
volatile unsigned char *addr = sn_io_addr(port);
*addr = val;
sn_mmiob();
}
static inline void
__sn_outw (unsigned short val, unsigned long port)
{
volatile unsigned short *addr = sn_io_addr(port);
*addr = val;
sn_mmiob();
}
static inline void
__sn_outl (unsigned int val, unsigned long port)
{
volatile unsigned int *addr = sn_io_addr(port);
*addr = val;
sn_mmiob();
}
/*
* The following routines are SN Platform specific, called when
* a reference is made to readX/writeX set macros. SN Platform
* readX set of macros ensures that Posted DMA writes on the
* Bridge is flushed.
*
* The routines should be self explainatory.
*/
static inline unsigned char
__sn_readb (void *addr)
{
unsigned char val;
val = *(volatile unsigned char *)addr;
sn_dma_flush((unsigned long)addr);
return val;
}
static inline unsigned short
__sn_readw (void *addr)
{
unsigned short val;
val = *(volatile unsigned short *)addr;
sn_dma_flush((unsigned long)addr);
return val;
}
static inline unsigned int
__sn_readl (void *addr)
{
unsigned int val;
val = *(volatile unsigned int *) addr;
sn_dma_flush((unsigned long)addr);
return val;
}
static inline unsigned long
__sn_readq (void *addr)
{
unsigned long val;
val = *(volatile unsigned long *) addr;
sn_dma_flush((unsigned long)addr);
return val;
}
/*
* For generic and SN2 kernels, we have a set of fast access
* PIO macros. These macros are provided on SN Platform
* because the normal inX and readX macros perform an
* additional task of flushing Post DMA request on the Bridge.
*
* These routines should be self explainatory.
*/
static inline unsigned int
sn_inb_fast (unsigned long port)
{
volatile unsigned char *addr = (unsigned char *)port;
unsigned char ret;
ret = *addr;
__sn_mf_a();
return ret;
}
static inline unsigned int
sn_inw_fast (unsigned long port)
{
volatile unsigned short *addr = (unsigned short *)port;
unsigned short ret;
ret = *addr;
__sn_mf_a();
return ret;
}
static inline unsigned int
sn_inl_fast (unsigned long port)
{
volatile unsigned int *addr = (unsigned int *)port;
unsigned int ret;
ret = *addr;
__sn_mf_a();
return ret;
}
static inline unsigned char
sn_readb_fast (void *addr)
{
return *(volatile unsigned char *)addr;
}
static inline unsigned short
sn_readw_fast (void *addr)
{
return *(volatile unsigned short *)addr;
}
static inline unsigned int
sn_readl_fast (void *addr)
{
return *(volatile unsigned int *) addr;
}
static inline unsigned long
sn_readq_fast (void *addr)
{
return *(volatile unsigned long *) addr;
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment