Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced

2016-09-21 Thread zhichang
Hi, Arnd,


On 2016年09月14日 22:23, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
>>>
>>> No need to guard includes with an #ifdef.
>> If remove #ifdef here, extio.h should not contain any function external 
>> declarations whose definitions are in
>> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
>  
> There is no problem with making declarations visible for functions that
> are not part of the kernel, we do that all the time.
> 
 +#define BUILDS_RW(bwl, type)  
   \
 +static inline void reads##bwl(const volatile void __iomem *addr,\
 +void *buffer, unsigned int count)   \
 +{   \
 +if (count) {\
 +type *buf = buffer; \
 +\
 +do {\
 +type x = __raw_read##bwl(addr); \
 +*buf++ = x; \
 +} while (--count);  \
 +}   \
 +}   \
 +\
 +static inline void writes##bwl(volatile void __iomem *addr, \
 +const void *buffer, unsigned int count) \
 +{   \
 +if (count) {\
 +const type *buf = buffer;   \
 +\
 +do {\
 +__raw_write##bwl(*buf++, addr); \
 +} while (--count);  \
 +}   \
 +}
 +
 +BUILDS_RW(b, u8)
>>>
>>> Why is this in here?
>> the readsb/writesb are defined in asm-generic/io.h which is included later, 
>> but the redefined insb/outsb need
>> to call them. Without these readsb/writesb definition before insb/outsb 
>> redefined, compile error occur.
>>
>> It seems that copy all the definitions of "asm-generic/io.h" is not a good 
>> idea, so I move the definitions of
>> those function needed here
>>
>> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this 
>> issue.
>>
>> #ifdef CONFIG_ARM64_INDIRECT_PIO
>> #define inb inb
>> extern u8 inb(unsigned long addr);
>>
>> #define outb outb
>> extern void outb(u8 value, unsigned long addr);
>>
>> #define insb insb
>> extern void insb(unsigned long addr, void *buffer, unsigned int count);
>>
>> #define outsb outsb
>> extern void outsb(unsigned long addr, const void *buffer, unsigned int 
>> count);
>> #endif
>>
>> and definitions of all these functions are in extio.c :
>>
>> u8 inb(unsigned long addr)
>> {
>> if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>> arm64_extio_ops->end < addr)
>> return readb(PCI_IOBASE + addr);
>> else
>> return arm64_extio_ops->pfin ?
>> arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>> addr + arm64_extio_ops->ptoffset, NULL,
>> sizeof(u8), 1) : -1;
>> }
>> .
> 
> Yes, sounds good.
> 
 @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void 
 __iomem *addr)
  #define IO_SPACE_LIMIT  (PCI_IO_SIZE - 1)
  #define PCI_IOBASE  ((void __iomem *)PCI_IO_START)
  
 +
 +/*
 + * redefine the in(s)b/out(s)b for indirect-IO.
 + */
 +#define inb inb
 +static inline u8 inb(unsigned long addr)
 +{
 +#ifdef CONFIG_ARM64_INDIRECT_PIO
 +if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
 +addr <= arm64_extio_ops->end)
 +return extio_inb(addr);
 +#endif
 +return readb(PCI_IOBASE + addr);
 +}
 +
>>>
>>> Looks ok, but you only seem to do this for the 8-bit
>>> accessors, when it should be done for 16-bit and 32-bit
>>> ones as well for consistency.
>> Hip06 LPC only support 8-bit I/O operations on the designated port.
> 
> That is an interesting limitation. Maybe still call the extio operations
> and have them do WARN_ON_ONCE() instead?
> 
> If you get a driver that calls inw/outw on the range that is owned
> by the LPC bus, you otherwise get an unhandled page fault in 

Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced

2016-09-17 Thread zhichang
Hi, Arnd,


On 2016年09月14日 22:23, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
>>>
>>> No need to guard includes with an #ifdef.
>> If remove #ifdef here, extio.h should not contain any function external 
>> declarations whose definitions are in
>> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
>  
> There is no problem with making declarations visible for functions that
> are not part of the kernel, we do that all the time.
> 
 +#define BUILDS_RW(bwl, type)  
   \
 +static inline void reads##bwl(const volatile void __iomem *addr,\
 +void *buffer, unsigned int count)   \
 +{   \
 +if (count) {\
 +type *buf = buffer; \
 +\
 +do {\
 +type x = __raw_read##bwl(addr); \
 +*buf++ = x; \
 +} while (--count);  \
 +}   \
 +}   \
 +\
 +static inline void writes##bwl(volatile void __iomem *addr, \
 +const void *buffer, unsigned int count) \
 +{   \
 +if (count) {\
 +const type *buf = buffer;   \
 +\
 +do {\
 +__raw_write##bwl(*buf++, addr); \
 +} while (--count);  \
 +}   \
 +}
 +
 +BUILDS_RW(b, u8)
>>>
>>> Why is this in here?
>> the readsb/writesb are defined in asm-generic/io.h which is included later, 
>> but the redefined insb/outsb need
>> to call them. Without these readsb/writesb definition before insb/outsb 
>> redefined, compile error occur.
>>
>> It seems that copy all the definitions of "asm-generic/io.h" is not a good 
>> idea, so I move the definitions of
>> those function needed here
>>
>> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this 
>> issue.
>>
>> #ifdef CONFIG_ARM64_INDIRECT_PIO
>> #define inb inb
>> extern u8 inb(unsigned long addr);
>>
>> #define outb outb
>> extern void outb(u8 value, unsigned long addr);
>>
>> #define insb insb
>> extern void insb(unsigned long addr, void *buffer, unsigned int count);
>>
>> #define outsb outsb
>> extern void outsb(unsigned long addr, const void *buffer, unsigned int 
>> count);
>> #endif
>>
>> and definitions of all these functions are in extio.c :
>>
>> u8 inb(unsigned long addr)
>> {
>> if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>> arm64_extio_ops->end < addr)
>> return readb(PCI_IOBASE + addr);
>> else
>> return arm64_extio_ops->pfin ?
>> arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>> addr + arm64_extio_ops->ptoffset, NULL,
>> sizeof(u8), 1) : -1;
>> }
>> .
> 
> Yes, sounds good.
> 
 @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void 
 __iomem *addr)
  #define IO_SPACE_LIMIT  (PCI_IO_SIZE - 1)
  #define PCI_IOBASE  ((void __iomem *)PCI_IO_START)
  
 +
 +/*
 + * redefine the in(s)b/out(s)b for indirect-IO.
 + */
 +#define inb inb
 +static inline u8 inb(unsigned long addr)
 +{
 +#ifdef CONFIG_ARM64_INDIRECT_PIO
 +if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
 +addr <= arm64_extio_ops->end)
 +return extio_inb(addr);
 +#endif
 +return readb(PCI_IOBASE + addr);
 +}
 +
>>>
>>> Looks ok, but you only seem to do this for the 8-bit
>>> accessors, when it should be done for 16-bit and 32-bit
>>> ones as well for consistency.
>> Hip06 LPC only support 8-bit I/O operations on the designated port.
> 
> That is an interesting limitation. Maybe still call the extio operations
> and have them do WARN_ON_ONCE() instead?
> 
> If you get a driver that calls inw/outw on the range that is owned
> by the LPC bus, you otherwise get an unhandled page fault in 

Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced

2016-09-14 Thread Arnd Bergmann
On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
> > 
> > No need to guard includes with an #ifdef.
> If remove #ifdef here, extio.h should not contain any function external 
> declarations whose definitions are in
> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
 
There is no problem with making declarations visible for functions that
are not part of the kernel, we do that all the time.

> >> +#define BUILDS_RW(bwl, type)  
> >>   \
> >> +static inline void reads##bwl(const volatile void __iomem *addr,\
> >> +void *buffer, unsigned int count)   \
> >> +{   \
> >> +if (count) {\
> >> +type *buf = buffer; \
> >> +\
> >> +do {\
> >> +type x = __raw_read##bwl(addr); \
> >> +*buf++ = x; \
> >> +} while (--count);  \
> >> +}   \
> >> +}   \
> >> +\
> >> +static inline void writes##bwl(volatile void __iomem *addr, \
> >> +const void *buffer, unsigned int count) \
> >> +{   \
> >> +if (count) {\
> >> +const type *buf = buffer;   \
> >> +\
> >> +do {\
> >> +__raw_write##bwl(*buf++, addr); \
> >> +} while (--count);  \
> >> +}   \
> >> +}
> >> +
> >> +BUILDS_RW(b, u8)
> > 
> > Why is this in here?
> the readsb/writesb are defined in asm-generic/io.h which is included later, 
> but the redefined insb/outsb need
> to call them. Without these readsb/writesb definition before insb/outsb 
> redefined, compile error occur.
> 
> It seems that copy all the definitions of "asm-generic/io.h" is not a good 
> idea, so I move the definitions of
> those function needed here
> 
> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this 
> issue.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO
> #define inb inb
> extern u8 inb(unsigned long addr);
> 
> #define outb outb
> extern void outb(u8 value, unsigned long addr);
> 
> #define insb insb
> extern void insb(unsigned long addr, void *buffer, unsigned int count);
> 
> #define outsb outsb
> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
> #endif
> 
> and definitions of all these functions are in extio.c :
> 
> u8 inb(unsigned long addr)
> {
> if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
> arm64_extio_ops->end < addr)
> return readb(PCI_IOBASE + addr);
> else
> return arm64_extio_ops->pfin ?
> arm64_extio_ops->pfin(arm64_extio_ops->devpara,
> addr + arm64_extio_ops->ptoffset, NULL,
> sizeof(u8), 1) : -1;
> }
> .

Yes, sounds good.

> >> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void 
> >> __iomem *addr)
> >>  #define IO_SPACE_LIMIT  (PCI_IO_SIZE - 1)
> >>  #define PCI_IOBASE  ((void __iomem *)PCI_IO_START)
> >>  
> >> +
> >> +/*
> >> + * redefine the in(s)b/out(s)b for indirect-IO.
> >> + */
> >> +#define inb inb
> >> +static inline u8 inb(unsigned long addr)
> >> +{
> >> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> >> +if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> >> +addr <= arm64_extio_ops->end)
> >> +return extio_inb(addr);
> >> +#endif
> >> +return readb(PCI_IOBASE + addr);
> >> +}
> >> +
> > 
> > Looks ok, but you only seem to do this for the 8-bit
> > accessors, when it should be done for 16-bit and 32-bit
> > ones as well for consistency.
> Hip06 LPC only support 8-bit I/O operations on the designated port.

That is an interesting limitation. Maybe still call the extio operations
and have them do WARN_ON_ONCE() instead?

If you get a driver that calls inw/outw on the range that is owned
by the LPC bus, you otherwise get an unhandled page fault in kernel
space, which is not as nice.

> >> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> >> new file mode 1006

Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced

2016-09-14 Thread zhichang.yuan
Hi, Arnd

On 2016/9/14 20:24, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:51 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" 
>>
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, 
>> for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Signed-off-by: zhichang.yuan 
> 
> Looks ok overall, but I have a couple of comments for details.
> 
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index bc3f00f..9579479 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>> default 16
>>  
>> +config ARM64_INDIRECT_PIO
>> +def_bool n
> 
> 'def_bool n' is the same as the shorter and more common 'bool'.
Yes. Will modify as bool "access peripherals with legacy I/O port"

> 
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 9b6e408..d3acf1f 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -34,6 +34,10 @@
>>  
>>  #include 
>>  
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#include 
>> +#endif
> 
> No need to guard includes with an #ifdef.
If remove #ifdef here, extio.h should not contain any function external 
declarations whose definitions are in
extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.


How about removing everything about the configure item "ARM64_INDIRECT_PIO"?
This will make the indirect-IO mechanism global on ARM64.
I worry about this mechanism is not so common, so using "ARM64_INDIRECT_PIO" 
make this feature optional.

> 
>> +#define BUILDS_RW(bwl, type)
>> \
>> +static inline void reads##bwl(const volatile void __iomem *addr,\
>> +void *buffer, unsigned int count)   \
>> +{   \
>> +if (count) {\
>> +type *buf = buffer; \
>> +\
>> +do {\
>> +type x = __raw_read##bwl(addr); \
>> +*buf++ = x; \
>> +} while (--count);  \
>> +}   \
>> +}   \
>> +\
>> +static inline void writes##bwl(volatile void __iomem *addr, \
>> +const void *buffer, unsigned int count) \
>> +{   \
>> +if (count) {\
>> +const type *buf = buffer;   \
>> +\
>> +do {\
>> +__raw_write##bwl(*buf++, addr); \
>> +} while (--count);  \
>> +}   \
>> +}
>> +
>> +BUILDS_RW(b, u8)
> 
> Why is this in here?
the readsb/writesb are defined in asm-generic/io.h which is included later, but 
the redefined insb/outsb need
to call them. Without these readsb/writesb definition before insb/outsb 
redefined, compile error occur.

It seems that copy all the definitions of "asm-generic/io.h" is not a good 
idea, so I move the definitions of
those function needed here

Ok. I think your idea below defining in(s)/out(s) in a c file can solve this 
issue.

#ifdef CONFIG_ARM64_INDIRECT_PIO
#define inb inb
extern u8 inb(unsigned long addr);

#define outb outb
extern void outb(u8 value, unsigned long addr);

#define insb insb
extern void insb(unsigned long addr, void *buffer, unsigned int count);

#define outsb outsb
extern void outsb(unsigned long addr, const void *buffer, unsigned int 

Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced

2016-09-14 Thread Arnd Bergmann
On Wednesday, September 14, 2016 8:15:51 PM CEST Zhichang Yuan wrote:
> From: "zhichang.yuan" 
> 
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
> 
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
> 
> Signed-off-by: zhichang.yuan 

Looks ok overall, but I have a couple of comments for details.

> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index bc3f00f..9579479 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
> default 16
>  
> +config ARM64_INDIRECT_PIO
> + def_bool n

'def_bool n' is the same as the shorter and more common 'bool'.

> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 9b6e408..d3acf1f 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -34,6 +34,10 @@
>  
>  #include 
>  
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#include 
> +#endif

No need to guard includes with an #ifdef.

> +#define BUILDS_RW(bwl, type) \
> +static inline void reads##bwl(const volatile void __iomem *addr, \
> + void *buffer, unsigned int count)   \
> +{\
> + if (count) {\
> + type *buf = buffer; \
> + \
> + do {\
> + type x = __raw_read##bwl(addr); \
> + *buf++ = x; \
> + } while (--count);  \
> + }   \
> +}\
> + \
> +static inline void writes##bwl(volatile void __iomem *addr,  \
> + const void *buffer, unsigned int count) \
> +{\
> + if (count) {\
> + const type *buf = buffer;   \
> + \
> + do {\
> + __raw_write##bwl(*buf++, addr); \
> + } while (--count);  \
> + }   \
> +}
> +
> +BUILDS_RW(b, u8)

Why is this in here?

> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void 
> __iomem *addr)
>  #define IO_SPACE_LIMIT   (PCI_IO_SIZE - 1)
>  #define PCI_IOBASE   ((void __iomem *)PCI_IO_START)
>  
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#define inb inb
> +static inline u8 inb(unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> + if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> + addr <= arm64_extio_ops->end)
> + return extio_inb(addr);
> +#endif
> + return readb(PCI_IOBASE + addr);
> +}
> +

Looks ok, but you only seem to do this for the 8-bit
accessors, when it should be done for 16-bit and 32-bit
ones as well for consistency.

> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> new file mode 100644
> index 000..1e7a9c5
> --- /dev/null
> +++ b/drivers/bus/extio.c
> @@ -0,0 +1,66 @@

This is in a globally visible directory

> +
> +struct extio_ops *arm64_extio_ops;

But the identifier uses an architecture specific prefix. Either
move the whole file into arch/arm64, or make the naming so that
it can be used for everything.

> +u8 __weak extio_inb(unsigned long addr)
> +{
> + return arm64_extio_ops->pfin ?
> + arm64_extio_ops->pfin(arm64_extio_ops->devpara,
> + addr + arm64_extio_ops->ptoffset, NULL,
> +