LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2] drivers/hvc: add missing __devexit_p()
From: Benjamin Herrenschmidt @ 2009-06-16  3:30 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: linuxppc-dev, Andrew Morton, linux-kernel
In-Reply-To: <1242632661-16198-1-git-send-email-vapier@gentoo.org>

On Mon, 2009-05-18 at 03:44 -0400, Mike Frysinger wrote:
> The remove function uses __devexit, so the .remove assignment needs
> __devexit_p() to fix a build error with hotplug disabled.
> 
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> CC: linuxppc-dev@ozlabs.org
> ---
> v2

Thanks. Andrew, I'm picking this one up.

Cheers,
Ben.

> 	- include all hvc files
> 
>  drivers/char/hvc_iseries.c |    2 +-
>  drivers/char/hvc_vio.c     |    2 +-
>  drivers/char/hvcs.c        |    2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c
> index 449727b..936d05b 100644
> --- a/drivers/char/hvc_iseries.c
> +++ b/drivers/char/hvc_iseries.c
> @@ -241,7 +241,7 @@ static int __devexit hvc_vio_remove(struct vio_dev *vdev)
>  static struct vio_driver hvc_vio_driver = {
>  	.id_table	= hvc_driver_table,
>  	.probe		= hvc_vio_probe,
> -	.remove		= hvc_vio_remove,
> +	.remove		= __devexit_p(hvc_vio_remove),
>  	.driver		= {
>  		.name	= hvc_driver_name,
>  		.owner	= THIS_MODULE,
> diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
> index bd62dc8..c72b994 100644
> --- a/drivers/char/hvc_vio.c
> +++ b/drivers/char/hvc_vio.c
> @@ -113,7 +113,7 @@ static int __devexit hvc_vio_remove(struct vio_dev *vdev)
>  static struct vio_driver hvc_vio_driver = {
>  	.id_table	= hvc_driver_table,
>  	.probe		= hvc_vio_probe,
> -	.remove		= hvc_vio_remove,
> +	.remove		= __devexit_p(hvc_vio_remove),
>  	.driver		= {
>  		.name	= hvc_driver_name,
>  		.owner	= THIS_MODULE,
> diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
> index c76bccf..2724d62 100644
> --- a/drivers/char/hvcs.c
> +++ b/drivers/char/hvcs.c
> @@ -868,7 +868,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
>  static struct vio_driver hvcs_vio_driver = {
>  	.id_table	= hvcs_driver_table,
>  	.probe		= hvcs_probe,
> -	.remove		= hvcs_remove,
> +	.remove		= __devexit_p(hvcs_remove),
>  	.driver		= {
>  		.name	= hvcs_driver_name,
>  		.owner	= THIS_MODULE,

^ permalink raw reply

* Re: [PATCH] RFC: powerpc: expose the multi-bit ops that underlie single-bit ops.
From: Benjamin Herrenschmidt @ 2009-06-16  3:53 UTC (permalink / raw)
  To: Geoff Thorpe; +Cc: linuxppc-dev
In-Reply-To: <1243361946-6771-1-git-send-email-Geoff.Thorpe@freescale.com>

On Tue, 2009-05-26 at 14:19 -0400, Geoff Thorpe wrote:
> NOT FOR COMMIT, THIS IS A REQUEST FOR FEEDBACK.
> 
> The bitops.h functions that operate on a single bit in a bitfield are
> implemented by operating on the corresponding word location. In all cases
> the inner logic appears to be valid if the mask being applied has more
> than one bit set, so this patch exposes those inner operations. Indeed,
> set_bits() was already available, but it duplicated code from set_bit()
> (rather than making the latter a wrapper) - it was also missing the
> PPC405_ERR77() workaround and the "volatile" address qualifier present in
> other APIs. This corrects that, and exposes the other multi-bit
> equivalents.
> 
> One advantage of these multi-bit forms is that they allow word-sized
> variables to essentially be their own spinlocks.

Hi ! Sorry for the delay, that was on my "have a look one of these days,
low priority" list for a bit too long :-)

> NB, the same factoring is possible in asm-generic/bitops/[non-]atomic.h.
> I would be happy to provide corresponding patches if this approach is
> deemed appropriate. Feedback would be most welcome.
> 
> Signed-off-by: Geoff Thorpe <Geoff.Thorpe@freescale.com>
> ---
>  arch/powerpc/include/asm/bitops.h |  111 +++++++++++++++++++++++--------------
>  1 files changed, 69 insertions(+), 42 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
> index 897eade..72de28c 100644
> --- a/arch/powerpc/include/asm/bitops.h
> +++ b/arch/powerpc/include/asm/bitops.h
> @@ -56,11 +56,10 @@
>  #define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
>  #define BITOP_LE_SWIZZLE	((BITS_PER_LONG-1) & ~0x7)
>  
> -static __inline__ void set_bit(int nr, volatile unsigned long *addr)
> +static __inline__ void set_bits(unsigned long mask, volatile unsigned long *_p)
>  {
>  	unsigned long old;
> -	unsigned long mask = BITOP_MASK(nr);
> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
> +	unsigned long *p = (unsigned long *)_p;
>  
>  	__asm__ __volatile__(
>  "1:"	PPC_LLARX "%0,0,%3	# set_bit\n"
> @@ -73,11 +72,16 @@ static __inline__ void set_bit(int nr, volatile unsigned long *addr)
>  	: "cc" );
>  }
>  
> -static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
> +static __inline__ void set_bit(int nr, volatile unsigned long *addr)
> +{
> +	set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
> +}

No objection with the above.

> +static __inline__ void clear_bits(unsigned long mask,
> +				volatile unsigned long *_p)
>  {
>  	unsigned long old;
> -	unsigned long mask = BITOP_MASK(nr);
> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
> +	unsigned long *p = (unsigned long *)_p;
>  
>  	__asm__ __volatile__(
>  "1:"	PPC_LLARX "%0,0,%3	# clear_bit\n"
> @@ -90,11 +94,16 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
>  	: "cc" );
>  }
>  
> -static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
> +static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
> +{
> +	clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
> +}

Looks good too.

> +static __inline__ void clear_bits_unlock(unsigned long mask,
> +					volatile unsigned long *_p)
>  {
>  	unsigned long old;
> -	unsigned long mask = BITOP_MASK(nr);
> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
> +	unsigned long *p = (unsigned long *)_p;
>  
>  	__asm__ __volatile__(
>  	LWSYNC_ON_SMP
> @@ -108,11 +117,16 @@ static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
>  	: "cc", "memory");
>  }
>  
> -static __inline__ void change_bit(int nr, volatile unsigned long *addr)
> +static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
> +{
> +	clear_bits_unlock(BITOP_MASK(nr), addr + BITOP_WORD(nr));
> +}

I'm not sure it's useful to provide a multi-bit variant of the
"lock" and "unlock" primitives. Do other archs do ?

> +static __inline__ void change_bits(unsigned long mask,
> +				volatile unsigned long *_p)
>  {
>  	unsigned long old;
> -	unsigned long mask = BITOP_MASK(nr);
> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
> +	unsigned long *p = (unsigned long *)_p;
>  
>  	__asm__ __volatile__(
>  "1:"	PPC_LLARX "%0,0,%3	# change_bit\n"
> @@ -125,12 +139,16 @@ static __inline__ void change_bit(int nr, volatile unsigned long *addr)
>  	: "cc" );
>  }
>  
> -static __inline__ int test_and_set_bit(unsigned long nr,
> -				       volatile unsigned long *addr)
> +static __inline__ void change_bit(int nr, volatile unsigned long *addr)
> +{
> +	change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
> +}

Ah, patch is getting confused between change_bit and
test_and_set_bit :-)

Now, you know what I'm thinking is ... Those are all the same except
for:

 - Barriers for lock and unlock variants
 - Barriers for "return" (aka test_and_set) variants
 - Actual op done on the mask

Maybe we can shrink that file significantly (and avoid the risk for
typos etc...) by generating them all from a macro.

Something like (typed directly into the mailer :-)

#define DEFINE_BITOP(op, prefix, postfix) \
	asm volatile (			  \
	prefix				  \
"1:"    PPC_LLARX "%0,0,%3\n"		  \
	__stringify(op) "%1,%0,%2\n"	  \
	PPC405_ERR77(0,%3)		  \
	PPC_STLCX "%1,0,%3\n"		  \
	"bne- 1b\n"			  \
	postfix				  \
	 : "=&r" (old), "=&r" (t)
	 : "r" (mask), "r" (p)
	 : "cc", "memory")

and so:

static inline void set_bits(unsigned long mask, volatile unsigned long *addr)
{
	unsigned long old, t;

	DEFINE_BITOP(or, "", "");
}

static inline void test_and_set_bits(unsigned long mask, volatile unsigned long *addr)
{
	unsigned long old, t;

	DEFINE_BITOP(or, LWSYNC_ON_SMP, ISYNC_ON_SMP);

	return (old & mask) != 0;
}

etc...

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] Fix oprofile sampling of marked events on POWER7
From: Benjamin Herrenschmidt @ 2009-06-16  4:12 UTC (permalink / raw)
  To: Maynard Johnson; +Cc: linuxppc-dev, Anton Blanchard
In-Reply-To: <4A364F4A.6060300@us.ibm.com>

On Mon, 2009-06-15 at 08:40 -0500, Maynard Johnson wrote:
> Looks like this posting got overlooked, so I'm re-posting the original patch.  Ben, can you please review?  BTW, Anton reported the problem that this patch fixes.

It was merged upstream after 2.6.30 -rc6, see commit e5fc948b...

Cheers,
Ben.

> Thanks.
> -Maynard
> 
> ==============================================================
> 
> 
> Description
> -----------
> Change ppc64 oprofile kernel driver to use the SLOT bits (MMCRA[37:39]only on 
> older processors where those bits are defined.
> 
> Background
> ----------
> The performance monitor unit of the 64-bit POWER processor family has the 
> ability to collect accurate instruction-level samples when profiling on marked 
> events (i.e., "PM_MRK_<event-name>").  In processors prior to POWER6, the MMCRA 
> register contained "slot information" that the oprofile kernel driver used to 
> adjust the value latched in the SIAR at the time of a PMU interrupt.  But as of 
> POWER6, these slot bits in MMCRA are no longer necessary for oprofile to use, 
> since the SIAR itself holds the accurate sampled instruction address.  With 
> POWER6, these MMCRA slot bits were zero'ed out by hardware so oprofile's use of 
> these slot bits was, in effect, a NOP.  But with POWER7, these bits are no 
> longer zero'ed out; however, they serve some other purpose rather than slot 
> information.  Thus, using these bits on POWER7 to adjust the SIAR value results 
> in samples being attributed to the wrong instructions.  The attached patch 
> changes the oprofile kernel driver to ignore these slot bits on all newer 
> processors starting with POWER6.
> 
> Thanks.
> -Maynard
> 
> Signed-off-by: Maynard Johnson <maynardj@us.ibm.com>
> 
> 
> 
> diff -paur linux/arch/powerpc/oprofile/op_model_power4.c linux-p7-oprofile-patch//arch/powerpc/oprofile/op_model_power4.c
> --- linux/arch/powerpc/oprofile/op_model_power4.c	2009-05-01 08:20:21.000000000 -0500
> +++ linux-p7-oprofile-patch//arch/powerpc/oprofile/op_model_power4.c	2009-05-01 08:20:05.000000000 -0500
> @@ -26,6 +26,7 @@
>  static unsigned long reset_value[OP_MAX_COUNTER];
> 
>  static int oprofile_running;
> +static int use_slot_nums;
> 
>  /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
>  static u32 mmcr0_val;
> @@ -61,6 +62,12 @@ static int power4_reg_setup(struct op_co
>  	else
>  		mmcr0_val |= MMCR0_PROBLEM_DISABLE;
> 
> +	if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) ||
> +	    __is_processor(PV_970) || __is_processor(PV_970FX) ||
> +	    __is_processor(PV_970MP) || __is_processor(PV_970GX) ||
> +	    __is_processor(PV_POWER5) || __is_processor(PV_POWER5p))
> +		use_slot_nums = 1;
> +
>  	return 0;
>  }
> 
> @@ -206,7 +213,7 @@ static unsigned long get_pc(struct pt_re
> 
>  	mmcra = mfspr(SPRN_MMCRA);
> 
> -	if (mmcra & MMCRA_SAMPLE_ENABLE) {
> +	if (use_slot_nums && (mmcra & MMCRA_SAMPLE_ENABLE)) {
>  		slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT);
>  		if (slot > 1)
>  			pc += 4 * (slot - 1);
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* linux-next: manual merge of the driver-core tree with the powerpc tree
From: Stephen Rothwell @ 2009-06-16  5:53 UTC (permalink / raw)
  To: Greg KH; +Cc: Roel Kluin, linux-kernel, ppc-dev, linux-next, Geert,
	Uytterhoeven

[-- Attachment #1: Type: text/plain, Size: 724 bytes --]

Hi Greg,

Today's linux-next merge of the driver-core tree got a conflict in
drivers/block/ps3disk.c between commits
6dee2c87ebbe5d7ce8c4c163966a0bd9c02c75ef ("block/ps3: remove driver_data
direct access of struct device") and
03fa68c245cccbcb99035cbabaa13b408ba91ab5 ("ps3: shorten ps3_system_bus_
[gs]et_driver_data to ps3_system_bus_[gs]et_drvdata") from the powerpc
tree and commit db7afa200c4ef6823a2a40e4ea1dd747775be01a ("block/ps3:
remove driver_data direct access of struct device") from the driver-core
tree.

I fixed it up (I used the version from the powerpc tree).  Greg, I think
the driver-core patch is no longer relevant.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* linux-next: manual merge of the driver-core tree with the powerpc tree
From: Stephen Rothwell @ 2009-06-16  5:58 UTC (permalink / raw)
  To: Greg KH; +Cc: Roel Kluin, linux-kernel, ppc-dev, linux-next, Geert,
	Uytterhoeven

[-- Attachment #1: Type: text/plain, Size: 727 bytes --]

Hi Greg,

Today's linux-next merge of the driver-core tree got a conflict in
drivers/block/ps3vram.c between commits
6dee2c87ebbe5d7ce8c4c163966a0bd9c02c75ef ("block/ps3: remove driver_data
direct access of struct device") and
03fa68c245cccbcb99035cbabaa13b408ba91ab5 ("ps3: shorten ps3_system_bus_
[gs]et_driver_data to ps3_system_bus_[gs]et_drvdata") from the powerpc
tree and commit db7afa200c4ef6823a2a40e4ea1dd747775be01a ("block/ps3:
remove driver_data direct access of struct device") from the driver-core
tree.

I fixed it up (used the powerpc tree version).  Again, Greg, I think the
driver-core tree version is no longer relevant.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: linux-next: manual merge of the driver-core tree with the powerpc tree
From: Greg KH @ 2009-06-16  6:18 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Roel Kluin, linux-kernel, ppc-dev, linux-next, Geert Uytterhoeven
In-Reply-To: <20090616155317.d1f1217e.sfr@canb.auug.org.au>

On Tue, Jun 16, 2009 at 03:53:17PM +1000, Stephen Rothwell wrote:
> Hi Greg,
> 
> Today's linux-next merge of the driver-core tree got a conflict in
> drivers/block/ps3disk.c between commits
> 6dee2c87ebbe5d7ce8c4c163966a0bd9c02c75ef ("block/ps3: remove driver_data
> direct access of struct device") and
> 03fa68c245cccbcb99035cbabaa13b408ba91ab5 ("ps3: shorten ps3_system_bus_
> [gs]et_driver_data to ps3_system_bus_[gs]et_drvdata") from the powerpc
> tree and commit db7afa200c4ef6823a2a40e4ea1dd747775be01a ("block/ps3:
> remove driver_data direct access of struct device") from the driver-core
> tree.
> 
> I fixed it up (I used the version from the powerpc tree).  Greg, I think
> the driver-core patch is no longer relevant.

I pushed out an update a number of hours ago (like 6+), so you should
have gotten it with this update.

When did you pull from my tree?  I also just sent a merge request to
Linus, so everything should be fixed up now.

thanks,

greg k-h

^ permalink raw reply

* linux-next: Linus/powerpc tree build warning
From: Stephen Rothwell @ 2009-06-16  6:24 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Suneel, linux-kernel, linuxppc-dev, linux-next, Stephen,
	John Linn

[-- Attachment #1: Type: text/plain, Size: 470 bytes --]

Hi Ben,

Today's linux-next build (powerpc ppc44x_defconfig) produced this warning:

drivers/video/xilinxfb.c: In function 'xilinxfb_assign':
drivers/video/xilinxfb.c:328: warning: cast to pointer from integer of different size

Introduced by commit dac4ccfb64bcdd5b4c248ccc22903d67486573cd ("fbdev:
Add PLB support and cleanup DCR in xilinxfb driver").
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: linux-next: manual merge of the driver-core tree with the powerpc tree
From: Stephen Rothwell @ 2009-06-16  6:42 UTC (permalink / raw)
  To: Greg KH; +Cc: Roel Kluin, linux-kernel, ppc-dev, linux-next, Geert,
	Uytterhoeven
In-Reply-To: <20090616061849.GA32109@kroah.com>

[-- Attachment #1: Type: text/plain, Size: 552 bytes --]

Hi Greg,

On Mon, 15 Jun 2009 23:18:49 -0700 Greg KH <greg@kroah.com> wrote:
>
> I pushed out an update a number of hours ago (like 6+), so you should
> have gotten it with this update.
> 
> When did you pull from my tree?  I also just sent a merge request to
> Linus, so everything should be fixed up now.

OK, thanks.  I fetch the trees usually between 8:30am and 10:00am UTC
+1000 (or +1100 in summer), so about 7 hours ago :-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: linux-next: Linus/powerpc tree build warning
From: Benjamin Herrenschmidt @ 2009-06-16  6:59 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Suneel, linux-kernel, linuxppc-dev, linux-next, John Linn
In-Reply-To: <20090616162429.07e74e75.sfr@canb.auug.org.au>

On Tue, 2009-06-16 at 16:24 +1000, Stephen Rothwell wrote:
> Hi Ben,
> 
> Today's linux-next build (powerpc ppc44x_defconfig) produced this warning:
> 
> drivers/video/xilinxfb.c: In function 'xilinxfb_assign':
> drivers/video/xilinxfb.c:328: warning: cast to pointer from integer of different size
> 
> Introduced by commit dac4ccfb64bcdd5b4c248ccc22903d67486573cd ("fbdev:
> Add PLB support and cleanup DCR in xilinxfb driver").

Known problem, a fix is currently being polished by Grant and John.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH 2.6.31] ehca: Tolerate dynamic memory operations and huge pages
From: Alexander Schmidt @ 2009-06-16  7:08 UTC (permalink / raw)
  To: Roland Dreier
  Cc: Hannes Hering, linux-kernel, ossrosch, linuxppc-dev, raisch, ewg,
	Hoang-Nam Nguyen
In-Reply-To: <adar5xoybwt.fsf@cisco.com>

Hi Roland,

thank you for taking a look at the code!

On Fri, 12 Jun 2009 21:50:58 -0700
Roland Dreier <rdreier@cisco.com> wrote:

> OK, one major issue with this patch and a few minor nits.
> 
> First, the major issue is that I don't see anything in the patch that
> changes the code in ehca_mem_notifier() in ehca_main.c:
> 
> 	case MEM_GOING_ONLINE:
> 	case MEM_GOING_OFFLINE:
> 		/* only ok if no hca is attached to the lpar */
> 		spin_lock_irqsave(&shca_list_lock, flags);
> 		if (list_empty(&shca_list)) {
> 			spin_unlock_irqrestore(&shca_list_lock, flags);
> 			return NOTIFY_OK;
> 		} else {
> 			spin_unlock_irqrestore(&shca_list_lock, flags);
> 			if (printk_timed_ratelimit(&ehca_dmem_warn_time,
> 						   30 * 1000))
> 				ehca_gen_err("DMEM operations are not allowed"
> 					     "in conjunction with eHCA");
> 			return NOTIFY_BAD;
> 		}
> 
> But your patch description says:
> 
>  > This patch implements toleration of dynamic memory operations....
> 
> But it seems you're still going to hit the same NOTIFY_BAD case above
> after your patch.  So something doesn't compute for me.  Could you
> explain more?

Yeah, the notifier code remains untouched as we still do not allow dynamic
memory operations _while_ our module is loaded. The patch allows the driver to
cope with DMEM operations that happened before the module was loaded, which
might result in a non-contiguous memory layout. When the driver registers
its global memory region in the system, the memory layout must be considered.

We chose the term "toleration" instead of "support" to illustrate this.

I'll put some more details into the changelog, incorporate the other comments
and send out a second version of the patch.

Thanks,
Alex

> 
> Second, a nit:
> 
>  > +#define EHCA_REG_MR 0
>  > +#define EHCA_REG_BUSMAP_MR (~0)
> 
> and you pass these as the reg_busmap parm in:
> 
>  >  int ehca_reg_mr(struct ehca_shca *shca,
>  >  		struct ehca_mr *e_mr,
>  >  		u64 *iova_start,
>  > @@ -991,7 +1031,8 @@
>  >  		struct ehca_pd *e_pd,
>  >  		struct ehca_mr_pginfo *pginfo,
>  >  		u32 *lkey, /*OUT*/
>  > -		u32 *rkey) /*OUT*/
>  > +		u32 *rkey, /*OUT*/
>  > +		int reg_busmap)
> 
> and test it as:
> 
>  > +	if (reg_busmap)
>  > +		ret = ehca_reg_bmap_mr_rpages(shca, e_mr, pginfo);
>  > +	else
>  > +		ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
> 
> So the ~0 for true looks a bit odd.  One option would be to make
> reg_busmap a bool, since that's how you're using it, but then you lose
> the nice self-documenting macro where you call things.
> 
> So I think it would be cleaner to do something like
> 
> enum ehca_reg_type {
> 	EHCA_REG_MR,
> 	EHCA_REG_BUSMAP_MR
> };
> 
> and make the "int reg_busmap" parameter into "enum ehca_reg_type reg_type"
> and have the code become
> 
> +	if (reg_type == EHCA_REG_BUSMAP_MR)
> +		ret = ehca_reg_bmap_mr_rpages(shca, e_mr, pginfo);
> +	else if (reg_type == EHCA_REG_MR)
> +		ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
> +	else
> +		ret = -EINVAL
> 
> or something like that.
> 
>  > +struct ib_dma_mapping_ops ehca_dma_mapping_ops = {
>  > +	.mapping_error = ehca_dma_mapping_error,
>  > +	.map_single = ehca_dma_map_single,
>  > +	.unmap_single = ehca_dma_unmap_single,
>  > +	.map_page = ehca_dma_map_page,
>  > +	.unmap_page = ehca_dma_unmap_page,
>  > +	.map_sg = ehca_dma_map_sg,
>  > +	.unmap_sg = ehca_dma_unmap_sg,
>  > +	.dma_address = ehca_dma_address,
>  > +	.dma_len = ehca_dma_len,
>  > +	.sync_single_for_cpu = ehca_dma_sync_single_for_cpu,
>  > +	.sync_single_for_device = ehca_dma_sync_single_for_device,
>  > +	.alloc_coherent = ehca_dma_alloc_coherent,
>  > +	.free_coherent = ehca_dma_free_coherent,
>  > +};
> 
> I always think structures like this are easier to read if you align the
> '=' signs.  But no big deal.
> 
>  > +	ret = ehca_create_busmap();
>  > +	if (ret) {
>  > +		ehca_gen_err("Cannot create busmap.");
>  > +		goto module_init2;
>  > +	}
>  > +
>  >  	ret = ibmebus_register_driver(&ehca_driver);
>  >  	if (ret) {
>  >  		ehca_gen_err("Cannot register eHCA device driver");
>  >  		ret = -EINVAL;
>  > -		goto module_init2;
>  > +		goto module_init3;
>  >  	}
>  >  
>  >  	ret = register_memory_notifier(&ehca_mem_nb);
>  >  	if (ret) {
>  >  		ehca_gen_err("Failed registering memory add/remove notifier");
>  > -		goto module_init3;
>  > +		goto module_init4;
> 
> Having to renumber unrelated things is when something changes is why I
> don't like this style of error path labels.  But I think it's well and
> truly too late to fix that in ehca.

^ permalink raw reply

* Re: [PATCH 2.6.31 try 2] ehca: Tolerate dynamic memory operations and huge pages
From: Alexander Schmidt @ 2009-06-16  7:10 UTC (permalink / raw)
  To: Hannes Hering
  Cc: rdreier, linux-kernel, ossrosch, linuxppc-dev, raisch, ewg,
	Hoang-Nam Nguyen
In-Reply-To: <200906091559.24661.hannes.hering@linux.vnet.ibm.com>

From: Hannes Hering <hering2@de.ibm.com>

This patch implements toleration of dynamic memory operations and 16 GB
gigantic pages. "Toleration" means that the driver can cope with dynamic
memory operations that happened before the driver was loaded. While using the
ehca driver, dynamic memory operations are still prohibited. On module load the
driver walks through available system memory, checks for available memory ranges
and then registers the kernel internal memory region accordingly. The
translation of address ranges is implemented via a 3-level busmap.

Signed-off-by: Hannes Hering <hering2@de.ibm.com>

---
This patch is built and tested against infiniband.git. Please apply for 2.6.31.

 drivers/infiniband/hw/ehca/ehca_main.c |   20 +
 drivers/infiniband/hw/ehca/ehca_mrmw.c |  508 ++++++++++++++++++++++++++++++++-
 drivers/infiniband/hw/ehca/ehca_mrmw.h |   13 
 3 files changed, 523 insertions(+), 18 deletions(-)

--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_main.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
 #include "ehca_tools.h"
 #include "hcp_if.h"
 
-#define HCAD_VERSION "0026"
+#define HCAD_VERSION "0027"
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
@@ -506,6 +506,7 @@ static int ehca_init_device(struct ehca_
 	shca->ib_device.detach_mcast	    = ehca_detach_mcast;
 	shca->ib_device.process_mad	    = ehca_process_mad;
 	shca->ib_device.mmap		    = ehca_mmap;
+	shca->ib_device.dma_ops		    = &ehca_dma_mapping_ops;
 
 	if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
 		shca->ib_device.uverbs_cmd_mask |=
@@ -1028,17 +1029,23 @@ static int __init ehca_module_init(void)
 		goto module_init1;
 	}
 
+	ret = ehca_create_busmap();
+	if (ret) {
+		ehca_gen_err("Cannot create busmap.");
+		goto module_init2;
+	}
+
 	ret = ibmebus_register_driver(&ehca_driver);
 	if (ret) {
 		ehca_gen_err("Cannot register eHCA device driver");
 		ret = -EINVAL;
-		goto module_init2;
+		goto module_init3;
 	}
 
 	ret = register_memory_notifier(&ehca_mem_nb);
 	if (ret) {
 		ehca_gen_err("Failed registering memory add/remove notifier");
-		goto module_init3;
+		goto module_init4;
 	}
 
 	if (ehca_poll_all_eqs != 1) {
@@ -1053,9 +1060,12 @@ static int __init ehca_module_init(void)
 
 	return 0;
 
-module_init3:
+module_init4:
 	ibmebus_unregister_driver(&ehca_driver);
 
+module_init3:
+	ehca_destroy_busmap();
+
 module_init2:
 	ehca_destroy_slab_caches();
 
@@ -1073,6 +1083,8 @@ static void __exit ehca_module_exit(void
 
 	unregister_memory_notifier(&ehca_mem_nb);
 
+	ehca_destroy_busmap();
+
 	ehca_destroy_slab_caches();
 
 	ehca_destroy_comp_pool();
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -53,6 +53,38 @@
 /* max number of rpages (per hcall register_rpages) */
 #define MAX_RPAGES 512
 
+/* DMEM toleration management */
+#define EHCA_SECTSHIFT        SECTION_SIZE_BITS
+#define EHCA_SECTSIZE          (1UL << EHCA_SECTSHIFT)
+#define EHCA_HUGEPAGESHIFT     34
+#define EHCA_HUGEPAGE_SIZE     (1UL << EHCA_HUGEPAGESHIFT)
+#define EHCA_HUGEPAGE_PFN_MASK ((EHCA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT)
+#define EHCA_INVAL_ADDR        0xFFFFFFFFFFFFFFFFULL
+#define EHCA_DIR_INDEX_SHIFT 13                   /* 8k Entries in 64k block */
+#define EHCA_TOP_INDEX_SHIFT (EHCA_DIR_INDEX_SHIFT * 2)
+#define EHCA_MAP_ENTRIES (1 << EHCA_DIR_INDEX_SHIFT)
+#define EHCA_TOP_MAP_SIZE (0x10000)               /* currently fixed map size */
+#define EHCA_DIR_MAP_SIZE (0x10000)
+#define EHCA_ENT_MAP_SIZE (0x10000)
+#define EHCA_INDEX_MASK (EHCA_MAP_ENTRIES - 1)
+
+static unsigned long ehca_mr_len;
+
+/*
+ * Memory map data structures
+ */
+struct ehca_dir_bmap {
+	u64 ent[EHCA_MAP_ENTRIES];
+};
+struct ehca_top_bmap {
+	struct ehca_dir_bmap *dir[EHCA_MAP_ENTRIES];
+};
+struct ehca_bmap {
+	struct ehca_top_bmap *top[EHCA_MAP_ENTRIES];
+};
+
+static struct ehca_bmap *ehca_bmap;
+
 static struct kmem_cache *mr_cache;
 static struct kmem_cache *mw_cache;
 
@@ -68,6 +100,8 @@ enum ehca_mr_pgsize {
 #define EHCA_MR_PGSHIFT1M  20
 #define EHCA_MR_PGSHIFT16M 24
 
+static u64 ehca_map_vaddr(void *caddr);
+
 static u32 ehca_encode_hwpage_size(u32 pgsize)
 {
 	int log = ilog2(pgsize);
@@ -135,7 +169,8 @@ struct ib_mr *ehca_get_dma_mr(struct ib_
 			goto get_dma_mr_exit0;
 		}
 
-		ret = ehca_reg_maxmr(shca, e_maxmr, (u64 *)KERNELBASE,
+		ret = ehca_reg_maxmr(shca, e_maxmr,
+				     (void *)ehca_map_vaddr((void *)KERNELBASE),
 				     mr_access_flags, e_pd,
 				     &e_maxmr->ib.ib_mr.lkey,
 				     &e_maxmr->ib.ib_mr.rkey);
@@ -251,7 +286,7 @@ struct ib_mr *ehca_reg_phys_mr(struct ib
 
 		ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
 				  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
-				  &e_mr->ib.ib_mr.rkey);
+				  &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
 		if (ret) {
 			ib_mr = ERR_PTR(ret);
 			goto reg_phys_mr_exit1;
@@ -370,7 +405,7 @@ reg_user_mr_fallback:
 
 	ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
 			  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
-			  &e_mr->ib.ib_mr.rkey);
+			  &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
 	if (ret == -EINVAL && pginfo.hwpage_size > PAGE_SIZE) {
 		ehca_warn(pd->device, "failed to register mr "
 			  "with hwpage_size=%llx", hwpage_size);
@@ -794,7 +829,7 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_
 	ret = ehca_reg_mr(shca, e_fmr, NULL,
 			  fmr_attr->max_pages * (1 << fmr_attr->page_shift),
 			  mr_access_flags, e_pd, &pginfo,
-			  &tmp_lkey, &tmp_rkey);
+			  &tmp_lkey, &tmp_rkey, EHCA_REG_MR);
 	if (ret) {
 		ib_fmr = ERR_PTR(ret);
 		goto alloc_fmr_exit1;
@@ -983,6 +1018,10 @@ free_fmr_exit0:
 
 /*----------------------------------------------------------------------*/
 
+static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
+				   struct ehca_mr *e_mr,
+				   struct ehca_mr_pginfo *pginfo);
+
 int ehca_reg_mr(struct ehca_shca *shca,
 		struct ehca_mr *e_mr,
 		u64 *iova_start,
@@ -991,7 +1030,8 @@ int ehca_reg_mr(struct ehca_shca *shca,
 		struct ehca_pd *e_pd,
 		struct ehca_mr_pginfo *pginfo,
 		u32 *lkey, /*OUT*/
-		u32 *rkey) /*OUT*/
+		u32 *rkey, /*OUT*/
+		enum ehca_reg_type reg_type)
 {
 	int ret;
 	u64 h_ret;
@@ -1015,7 +1055,13 @@ int ehca_reg_mr(struct ehca_shca *shca,
 
 	e_mr->ipz_mr_handle = hipzout.handle;
 
-	ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
+	if (reg_type == EHCA_REG_BUSMAP_MR)
+		ret = ehca_reg_bmap_mr_rpages(shca, e_mr, pginfo);
+	else if (reg_type == EHCA_REG_MR)
+		ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
+	else
+		ret = -EINVAL;
+
 	if (ret)
 		goto ehca_reg_mr_exit1;
 
@@ -1316,7 +1362,7 @@ int ehca_rereg_mr(struct ehca_shca *shca
 		e_mr->fmr_map_cnt = save_mr.fmr_map_cnt;
 
 		ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl,
-				  e_pd, pginfo, lkey, rkey);
+				  e_pd, pginfo, lkey, rkey, EHCA_REG_MR);
 		if (ret) {
 			u32 offset = (u64)(&e_mr->flags) - (u64)e_mr;
 			memcpy(&e_mr->flags, &(save_mr.flags),
@@ -1409,7 +1455,7 @@ int ehca_unmap_one_fmr(struct ehca_shca 
 	ret = ehca_reg_mr(shca, e_fmr, NULL,
 			  (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
 			  e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
-			  &tmp_rkey);
+			  &tmp_rkey, EHCA_REG_MR);
 	if (ret) {
 		u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr;
 		memcpy(&e_fmr->flags, &(save_mr.flags),
@@ -1478,6 +1524,90 @@ ehca_reg_smr_exit0:
 } /* end ehca_reg_smr() */
 
 /*----------------------------------------------------------------------*/
+static inline void *ehca_calc_sectbase(int top, int dir, int idx)
+{
+	unsigned long ret = idx;
+	ret |= dir << EHCA_DIR_INDEX_SHIFT;
+	ret |= top << EHCA_TOP_INDEX_SHIFT;
+	return abs_to_virt(ret << SECTION_SIZE_BITS);
+}
+
+#define ehca_bmap_valid(entry) \
+	((u64)entry != (u64)EHCA_INVAL_ADDR)
+
+static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
+			       struct ehca_shca *shca, struct ehca_mr *mr,
+			       struct ehca_mr_pginfo *pginfo)
+{
+	u64 h_ret = 0;
+	unsigned long page = 0;
+	u64 rpage = virt_to_abs(kpage);
+	int page_count;
+
+	void *sectbase = ehca_calc_sectbase(top, dir, idx);
+	if ((unsigned long)sectbase & (pginfo->hwpage_size - 1)) {
+		ehca_err(&shca->ib_device, "reg_mr_section will probably fail:"
+					   "hwpage_size does not fit to "
+					   "section start address");
+	}
+	page_count = EHCA_SECTSIZE / pginfo->hwpage_size;
+
+	while (page < page_count) {
+		u64 rnum;
+		for (rnum = 0; (rnum < MAX_RPAGES) && (page < page_count);
+		     rnum++) {
+			void *pg = sectbase + ((page++) * pginfo->hwpage_size);
+			kpage[rnum] = virt_to_abs(pg);
+		}
+
+		h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, mr,
+			ehca_encode_hwpage_size(pginfo->hwpage_size),
+			0, rpage, rnum);
+
+		if ((h_ret != H_SUCCESS) && (h_ret != H_PAGE_REGISTERED)) {
+			ehca_err(&shca->ib_device, "register_rpage_mr failed");
+			return h_ret;
+		}
+	}
+	return h_ret;
+}
+
+static u64 ehca_reg_mr_sections(int top, int dir, u64 *kpage,
+				struct ehca_shca *shca, struct ehca_mr *mr,
+				struct ehca_mr_pginfo *pginfo)
+{
+	u64 hret = H_SUCCESS;
+	int idx;
+
+	for (idx = 0; idx < EHCA_MAP_ENTRIES; idx++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]->ent[idx]))
+			continue;
+
+		hret = ehca_reg_mr_section(top, dir, idx, kpage, shca, mr,
+					   pginfo);
+		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
+				return hret;
+	}
+	return hret;
+}
+
+static u64 ehca_reg_mr_dir_sections(int top, u64 *kpage, struct ehca_shca *shca,
+				    struct ehca_mr *mr,
+				    struct ehca_mr_pginfo *pginfo)
+{
+	u64 hret = H_SUCCESS;
+	int dir;
+
+	for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+			continue;
+
+		hret = ehca_reg_mr_sections(top, dir, kpage, shca, mr, pginfo);
+		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
+				return hret;
+	}
+	return hret;
+}
 
 /* register internal max-MR to internal SHCA */
 int ehca_reg_internal_maxmr(
@@ -1495,6 +1625,11 @@ int ehca_reg_internal_maxmr(
 	u32 num_hwpages;
 	u64 hw_pgsize;
 
+	if (!ehca_bmap) {
+		ret = -EFAULT;
+		goto ehca_reg_internal_maxmr_exit0;
+	}
+
 	e_mr = ehca_mr_new();
 	if (!e_mr) {
 		ehca_err(&shca->ib_device, "out of memory");
@@ -1504,8 +1639,8 @@ int ehca_reg_internal_maxmr(
 	e_mr->flags |= EHCA_MR_FLAG_MAXMR;
 
 	/* register internal max-MR on HCA */
-	size_maxmr = (u64)high_memory - PAGE_OFFSET;
-	iova_start = (u64 *)KERNELBASE;
+	size_maxmr = ehca_mr_len;
+	iova_start = (u64 *)ehca_map_vaddr((void *)KERNELBASE);
 	ib_pbuf.addr = 0;
 	ib_pbuf.size = size_maxmr;
 	num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
@@ -1524,7 +1659,7 @@ int ehca_reg_internal_maxmr(
 
 	ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd,
 			  &pginfo, &e_mr->ib.ib_mr.lkey,
-			  &e_mr->ib.ib_mr.rkey);
+			  &e_mr->ib.ib_mr.rkey, EHCA_REG_BUSMAP_MR);
 	if (ret) {
 		ehca_err(&shca->ib_device, "reg of internal max MR failed, "
 			 "e_mr=%p iova_start=%p size_maxmr=%llx num_kpages=%x "
@@ -2077,8 +2212,8 @@ int ehca_mr_is_maxmr(u64 size,
 		     u64 *iova_start)
 {
 	/* a MR is treated as max-MR only if it fits following: */
-	if ((size == ((u64)high_memory - PAGE_OFFSET)) &&
-	    (iova_start == (void *)KERNELBASE)) {
+	if ((size == ehca_mr_len) &&
+	    (iova_start == (void *)ehca_map_vaddr((void *)KERNELBASE))) {
 		ehca_gen_dbg("this is a max-MR");
 		return 1;
 	} else
@@ -2184,3 +2319,350 @@ void ehca_cleanup_mrmw_cache(void)
 	if (mw_cache)
 		kmem_cache_destroy(mw_cache);
 }
+
+static inline int ehca_init_top_bmap(struct ehca_top_bmap *ehca_top_bmap,
+				     int dir)
+{
+	if (!ehca_bmap_valid(ehca_top_bmap->dir[dir])) {
+		ehca_top_bmap->dir[dir] =
+			kmalloc(sizeof(struct ehca_dir_bmap), GFP_KERNEL);
+		if (!ehca_top_bmap->dir[dir])
+			return -ENOMEM;
+		/* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+		memset(ehca_top_bmap->dir[dir], 0xFF, EHCA_ENT_MAP_SIZE);
+	}
+	return 0;
+}
+
+static inline int ehca_init_bmap(struct ehca_bmap *ehca_bmap, int top, int dir)
+{
+	if (!ehca_bmap_valid(ehca_bmap->top[top])) {
+		ehca_bmap->top[top] =
+			kmalloc(sizeof(struct ehca_top_bmap), GFP_KERNEL);
+		if (!ehca_bmap->top[top])
+			return -ENOMEM;
+		/* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+		memset(ehca_bmap->top[top], 0xFF, EHCA_DIR_MAP_SIZE);
+	}
+	return ehca_init_top_bmap(ehca_bmap->top[top], dir);
+}
+
+static inline int ehca_calc_index(unsigned long i, unsigned long s)
+{
+	return (i >> s) & EHCA_INDEX_MASK;
+}
+
+void ehca_destroy_busmap(void)
+{
+	int top, dir;
+
+	if (!ehca_bmap)
+		return;
+
+	for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]))
+			continue;
+		for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
+			if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+				continue;
+
+			kfree(ehca_bmap->top[top]->dir[dir]);
+		}
+
+		kfree(ehca_bmap->top[top]);
+	}
+
+	kfree(ehca_bmap);
+	ehca_bmap = NULL;
+}
+
+static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages)
+{
+	unsigned long i, start_section, end_section;
+	int top, dir, idx;
+
+	if (!nr_pages)
+		return 0;
+
+	if (!ehca_bmap) {
+		ehca_bmap = kmalloc(sizeof(struct ehca_bmap), GFP_KERNEL);
+		if (!ehca_bmap)
+			return -ENOMEM;
+		/* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+		memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE);
+	}
+
+	start_section = phys_to_abs(pfn * PAGE_SIZE) / EHCA_SECTSIZE;
+	end_section = phys_to_abs((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
+	for (i = start_section; i < end_section; i++) {
+		int ret;
+		top = ehca_calc_index(i, EHCA_TOP_INDEX_SHIFT);
+		dir = ehca_calc_index(i, EHCA_DIR_INDEX_SHIFT);
+		idx = i & EHCA_INDEX_MASK;
+
+		ret = ehca_init_bmap(ehca_bmap, top, dir);
+		if (ret) {
+			ehca_destroy_busmap();
+			return ret;
+		}
+		ehca_bmap->top[top]->dir[dir]->ent[idx] = ehca_mr_len;
+		ehca_mr_len += EHCA_SECTSIZE;
+	}
+	return 0;
+}
+
+static int ehca_is_hugepage(unsigned long pfn)
+{
+	int page_order;
+
+	if (pfn & EHCA_HUGEPAGE_PFN_MASK)
+		return 0;
+
+	page_order = compound_order(pfn_to_page(pfn));
+	if (page_order + PAGE_SHIFT != EHCA_HUGEPAGESHIFT)
+		return 0;
+
+	return 1;
+}
+
+static int ehca_create_busmap_callback(unsigned long initial_pfn,
+				       unsigned long total_nr_pages, void *arg)
+{
+	int ret;
+	unsigned long pfn, start_pfn, end_pfn, nr_pages;
+
+	if ((total_nr_pages * PAGE_SIZE) < EHCA_HUGEPAGE_SIZE)
+		return ehca_update_busmap(initial_pfn, total_nr_pages);
+
+	/* Given chunk is >= 16GB -> check for hugepages */
+	start_pfn = initial_pfn;
+	end_pfn = initial_pfn + total_nr_pages;
+	pfn = start_pfn;
+
+	while (pfn < end_pfn) {
+		if (ehca_is_hugepage(pfn)) {
+			/* Add mem found in front of the hugepage */
+			nr_pages = pfn - start_pfn;
+			ret = ehca_update_busmap(start_pfn, nr_pages);
+			if (ret)
+				return ret;
+			/* Skip the hugepage */
+			pfn += (EHCA_HUGEPAGE_SIZE / PAGE_SIZE);
+			start_pfn = pfn;
+		} else
+			pfn += (EHCA_SECTSIZE / PAGE_SIZE);
+	}
+
+	/* Add mem found behind the hugepage(s)  */
+	nr_pages = pfn - start_pfn;
+	return ehca_update_busmap(start_pfn, nr_pages);
+}
+
+int ehca_create_busmap(void)
+{
+	int ret;
+
+	ehca_mr_len = 0;
+	ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
+				   ehca_create_busmap_callback);
+	return ret;
+}
+
+static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
+				   struct ehca_mr *e_mr,
+				   struct ehca_mr_pginfo *pginfo)
+{
+	int top;
+	u64 hret, *kpage;
+
+	kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+	if (!kpage) {
+		ehca_err(&shca->ib_device, "kpage alloc failed");
+		return -ENOMEM;
+	}
+	for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]))
+			continue;
+		hret = ehca_reg_mr_dir_sections(top, kpage, shca, e_mr, pginfo);
+		if ((hret != H_PAGE_REGISTERED) && (hret != H_SUCCESS))
+			break;
+	}
+
+	ehca_free_fw_ctrlblock(kpage);
+
+	if (hret == H_SUCCESS)
+		return 0; /* Everything is fine */
+	else {
+		ehca_err(&shca->ib_device, "ehca_reg_bmap_mr_rpages failed, "
+				 "h_ret=%lli e_mr=%p top=%x lkey=%x "
+				 "hca_hndl=%llx mr_hndl=%llx", hret, e_mr, top,
+				 e_mr->ib.ib_mr.lkey,
+				 shca->ipz_hca_handle.handle,
+				 e_mr->ipz_mr_handle.handle);
+		return ehca2ib_return_code(hret);
+	}
+}
+
+static u64 ehca_map_vaddr(void *caddr)
+{
+	int top, dir, idx;
+	unsigned long abs_addr, offset;
+	u64 entry;
+
+	if (!ehca_bmap)
+		return EHCA_INVAL_ADDR;
+
+	abs_addr = virt_to_abs(caddr);
+	top = ehca_calc_index(abs_addr, EHCA_TOP_INDEX_SHIFT + EHCA_SECTSHIFT);
+	if (!ehca_bmap_valid(ehca_bmap->top[top]))
+		return EHCA_INVAL_ADDR;
+
+	dir = ehca_calc_index(abs_addr, EHCA_DIR_INDEX_SHIFT + EHCA_SECTSHIFT);
+	if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+		return EHCA_INVAL_ADDR;
+
+	idx = ehca_calc_index(abs_addr, EHCA_SECTSHIFT);
+
+	entry = ehca_bmap->top[top]->dir[dir]->ent[idx];
+	if (ehca_bmap_valid(entry)) {
+		offset = (unsigned long)caddr & (EHCA_SECTSIZE - 1);
+		return entry | offset;
+	} else
+		return EHCA_INVAL_ADDR;
+}
+
+static int ehca_dma_mapping_error(struct ib_device *dev, u64 dma_addr)
+{
+	return dma_addr == EHCA_INVAL_ADDR;
+}
+
+static u64 ehca_dma_map_single(struct ib_device *dev, void *cpu_addr,
+			       size_t size, enum dma_data_direction direction)
+{
+	if (cpu_addr)
+		return ehca_map_vaddr(cpu_addr);
+	else
+		return EHCA_INVAL_ADDR;
+}
+
+static void ehca_dma_unmap_single(struct ib_device *dev, u64 addr, size_t size,
+				  enum dma_data_direction direction)
+{
+	/* This is only a stub; nothing to be done here */
+}
+
+static u64 ehca_dma_map_page(struct ib_device *dev, struct page *page,
+			     unsigned long offset, size_t size,
+			     enum dma_data_direction direction)
+{
+	u64 addr;
+
+	if (offset + size > PAGE_SIZE)
+		return EHCA_INVAL_ADDR;
+
+	addr = ehca_map_vaddr(page_address(page));
+	if (!ehca_dma_mapping_error(dev, addr))
+		addr += offset;
+
+	return addr;
+}
+
+static void ehca_dma_unmap_page(struct ib_device *dev, u64 addr, size_t size,
+				enum dma_data_direction direction)
+{
+	/* This is only a stub; nothing to be done here */
+}
+
+static int ehca_dma_map_sg(struct ib_device *dev, struct scatterlist *sgl,
+			   int nents, enum dma_data_direction direction)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i) {
+		u64 addr;
+		addr = ehca_map_vaddr(sg_virt(sg));
+		if (ehca_dma_mapping_error(dev, addr))
+			return 0;
+
+		sg->dma_address = addr;
+		sg->dma_length = sg->length;
+	}
+	return nents;
+}
+
+static void ehca_dma_unmap_sg(struct ib_device *dev, struct scatterlist *sg,
+			      int nents, enum dma_data_direction direction)
+{
+	/* This is only a stub; nothing to be done here */
+}
+
+static u64 ehca_dma_address(struct ib_device *dev, struct scatterlist *sg)
+{
+	return sg->dma_address;
+}
+
+static unsigned int ehca_dma_len(struct ib_device *dev, struct scatterlist *sg)
+{
+	return sg->length;
+}
+
+static void ehca_dma_sync_single_for_cpu(struct ib_device *dev, u64 addr,
+					 size_t size,
+					 enum dma_data_direction dir)
+{
+	dma_sync_single_for_cpu(dev->dma_device, addr, size, dir);
+}
+
+static void ehca_dma_sync_single_for_device(struct ib_device *dev, u64 addr,
+					    size_t size,
+					    enum dma_data_direction dir)
+{
+	dma_sync_single_for_device(dev->dma_device, addr, size, dir);
+}
+
+static void *ehca_dma_alloc_coherent(struct ib_device *dev, size_t size,
+				     u64 *dma_handle, gfp_t flag)
+{
+	struct page *p;
+	void *addr = NULL;
+	u64 dma_addr;
+
+	p = alloc_pages(flag, get_order(size));
+	if (p) {
+		addr = page_address(p);
+		dma_addr = ehca_map_vaddr(addr);
+		if (ehca_dma_mapping_error(dev, dma_addr)) {
+			free_pages((unsigned long)addr,	get_order(size));
+			return NULL;
+		}
+		if (dma_handle)
+			*dma_handle = dma_addr;
+		return addr;
+	}
+	return NULL;
+}
+
+static void ehca_dma_free_coherent(struct ib_device *dev, size_t size,
+				   void *cpu_addr, u64 dma_handle)
+{
+	if (cpu_addr && size)
+		free_pages((unsigned long)cpu_addr, get_order(size));
+}
+
+
+struct ib_dma_mapping_ops ehca_dma_mapping_ops = {
+	.mapping_error          = ehca_dma_mapping_error,
+	.map_single             = ehca_dma_map_single,
+	.unmap_single           = ehca_dma_unmap_single,
+	.map_page               = ehca_dma_map_page,
+	.unmap_page             = ehca_dma_unmap_page,
+	.map_sg                 = ehca_dma_map_sg,
+	.unmap_sg               = ehca_dma_unmap_sg,
+	.dma_address            = ehca_dma_address,
+	.dma_len                = ehca_dma_len,
+	.sync_single_for_cpu    = ehca_dma_sync_single_for_cpu,
+	.sync_single_for_device = ehca_dma_sync_single_for_device,
+	.alloc_coherent         = ehca_dma_alloc_coherent,
+	.free_coherent          = ehca_dma_free_coherent,
+};
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_mrmw.h
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_mrmw.h
@@ -42,6 +42,11 @@
 #ifndef _EHCA_MRMW_H_
 #define _EHCA_MRMW_H_
 
+enum ehca_reg_type {
+	EHCA_REG_MR,
+	EHCA_REG_BUSMAP_MR
+};
+
 int ehca_reg_mr(struct ehca_shca *shca,
 		struct ehca_mr *e_mr,
 		u64 *iova_start,
@@ -50,7 +55,8 @@ int ehca_reg_mr(struct ehca_shca *shca,
 		struct ehca_pd *e_pd,
 		struct ehca_mr_pginfo *pginfo,
 		u32 *lkey,
-		u32 *rkey);
+		u32 *rkey,
+		enum ehca_reg_type reg_type);
 
 int ehca_reg_mr_rpages(struct ehca_shca *shca,
 		       struct ehca_mr *e_mr,
@@ -118,4 +124,9 @@ void ehca_mrmw_reverse_map_acl(const u32
 
 void ehca_mr_deletenew(struct ehca_mr *mr);
 
+int ehca_create_busmap(void);
+
+void ehca_destroy_busmap(void);
+
+extern struct ib_dma_mapping_ops ehca_dma_mapping_ops;
 #endif  /*_EHCA_MRMW_H_*/

^ permalink raw reply

* Re: [PATCH 2/2] uio: add an of_genirq driver
From: Wolfram Sang @ 2009-06-16  9:04 UTC (permalink / raw)
  To: Grant Likely
  Cc: devicetree-discuss, Hans J. Koch, linux-kernel, linuxppc-dev,
	Greg KH
In-Reply-To: <fa686aa40906140740m43e9dd8am4d242310f681c95c@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2107 bytes --]


> > diff --git a/Documentation/powerpc/dts-bindings/uio-generic.txt b/Documentation/powerpc/dts-bindings/uio-generic.txt
> > new file mode 100644
> > index 0000000..8ad9861
> > --- /dev/null
> > +++ b/Documentation/powerpc/dts-bindings/uio-generic.txt
> > @@ -0,0 +1,16 @@
> > +UIO for custom devices
> > +
> > +A device which will be mapped using the UIO subsystem.
> > +
> > +Properties:
> > + - compatible : should contain the specific model used, followed by
> > +                "generic-uio".
> > + - reg : address range(s) of the device (up to MAX_UIO_MAPS)
> > + - interrupts : interrupt of the device
> > +
> > +Example:
> > +        c64fpga@0 {
> > +                compatible = "ptx,c64fpga001", "generic-uio";
> > +                reg = <0x0 0x10000>;
> > +                interrupts = <0 0 3>;
> > +        };
> 
> Hmmm, I'm not happy about this.  The device tree describes the
> hardware, not the way Linux uses the hardware.  UIO definitely falls
> into the category of Linux implementation detail.

Yes, I am aware of that. I just started with the mechanisms which are available
today and hoped we could find some compatible-value which will suit all needs.

> This should be approached from the other way around.  Either the
> generic-uio of_platform driver should contain an explicit list of
> devices to be handled by UIO,

Well, that could lead to a quite huge match_table over time.

> or the OF infrastructure should be modified to allow things like force
> binding of_devices to of_drivers at runtime.

That is an interesting idea. I could imagine something like a 'new_compatible"
entry in the sysfs-section of the driver similar to 'new_id' for PCI. After
writing a new compatible-string into it, matching will triggered again with the
new entry added. That could (should?) also be placed at the of-core-level. Or
did you have something else in mind?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH V2 2/2] mtd/maps/mtd-ram: add an of-platform driver
From: Wolfram Sang @ 2009-06-16  9:09 UTC (permalink / raw)
  To: David Woodhouse
  Cc: devicetree-discuss, albrecht.dress, linuxppc-dev, linux-mtd,
	Ben Dooks
In-Reply-To: <1244276049.3751.1176.camel@macbook.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 698 bytes --]

On Sat, Jun 06, 2009 at 09:14:08AM +0100, David Woodhouse wrote:
> On Fri, 2009-06-05 at 14:05 +0200, Wolfram Sang wrote:
> > Create an of-aware driver using the now exported generic functions from
> > plat-ram.c. Also add the documentation for the binding. Partitions are
> > not yet supported. Tested on a phyCORE-MPC5200B-IO.
> 
> Do we have an ack for the device-tree bindings? 

Well, Grant acked so far and he surely has a voice in the device-tree-world :)
Or do you want a specific ack for that?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH V2 2/2] mtd/maps/mtd-ram: add an of-platform driver
From: Wolfram Sang @ 2009-06-16  9:18 UTC (permalink / raw)
  To: Albrecht Dreß
  Cc: devicetree-discuss, linuxppc-dev, linux-mtd, Ben Dooks,
	David Woodhouse
In-Reply-To: <1245087807.3185.0@antares>

[-- Attachment #1: Type: text/plain, Size: 860 bytes --]

On Mon, Jun 15, 2009 at 07:43:20PM +0200, Albrecht Dreß wrote:
> Am 05.06.09 14:05 schrieb(en) Wolfram Sang:
>> Create an of-aware driver using the now exported generic functions  
>> from plat-ram.c. Also add the documentation for the binding.  
>> Partitions are not yet supported. Tested on a phyCORE-MPC5200B-IO.
>
> Dumb question: what is the current status of this patch?  I ask because  

I don't know.

David wondered if 'of_physmap' could be used, so I wrote what I experienced
during development. I can't tell if this helped the case.

Grant wondered if we need a bankwidth. IMHO it is needed for now, but I don't
know if this is a common agreement.

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: Chipselect in SPI binding with mpc5200-psc-spi
From: Kári Davíðsson @ 2009-06-16 10:41 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <fa686aa40906151031p74636557oc1ab173236d0a81b@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1261 bytes --]

Now my driver gets probed.

This "modalias" error was due to wrong "compatible" attribute of
my of node.

But I still need to have the call to of_register_spi_devices().

The attached patch shows what I mean.

rg
kd

Grant Likely wrote:
> On Mon, Jun 15, 2009 at 10:36 AM, Kári
> Davíðsson<kari.davidsson@marel.com> wrote:
>> Is this true?
>>
>> Grant Likely wrote:
>>> Yes, this is right.  The psc_spi driver automatically registers all
>>> spi children that it finds in the device tree onto the SPI bus.
>>> Therefore registering an spi_driver() is the right thing to do.
>> I am writing an SPI protocol driver and I find that my driver
>> is never probed.
>>
>> I tried to add and call to of_register_spi_devices() in the
>> drivers/spi/mpc52xx_psc_spi.c::mpc52xx_psc_spi_of_probe() function,
>> without much effect besided that the DTS node is parsed but the driver probe
>> is not called, actually it complains about a modalias for my node is
>> missing.
> 
> What do you see when you look in /sys/bus/spi/devices?  You should see
> a directory for your device.  What do you see in /sys/bus/spi/drivers?
>  In here you should see your driver.  If they are both there, then you
> just have a problem matching your driver name to the device name.
> 
> g.
> 

[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 1677 bytes --]

Index: drivers/spi/mpc52xx_psc_spi.c
===================================================================
--- drivers/spi/mpc52xx_psc_spi.c	(revision 548)
+++ drivers/spi/mpc52xx_psc_spi.c	(working copy)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_spi.h>
 
 #include <asm/mpc52xx.h>
 #include <asm/mpc52xx_psc.h>
@@ -371,7 +372,7 @@
 
 /* bus_num is used only for the case dev->platform_data == NULL */
 static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
-				u32 size, unsigned int irq, s16 bus_num)
+				u32 size, unsigned int irq, s16 bus_num, struct spi_master ** pmaster)
 {
 	struct fsl_spi_platform_data *pdata = dev->platform_data;
 	struct mpc52xx_psc_spi *mps;
@@ -439,6 +440,10 @@
 	if (ret < 0)
 		goto unreg_master;
 
+    dev_info(dev, "Activated\n");
+
+    *pmaster = master;
+
 	return ret;
 
 unreg_master:
@@ -474,6 +479,8 @@
 	const u32 *regaddr_p;
 	u64 regaddr64, size64;
 	s16 id = -1;
+    int res;
+    struct spi_master * master = NULL;;
 
 	regaddr_p = of_get_address(op->node, 0, &size64, NULL);
 	if (!regaddr_p) {
@@ -495,8 +502,16 @@
 		id = *psc_nump + 1;
 	}
 
-	return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
-					irq_of_parse_and_map(op->node, 0), id);
+	res = mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
+					irq_of_parse_and_map(op->node, 0), id, &master);
+
+    if( master != NULL )
+    {
+        /* Add any subnodes on the SPI bus */
+        of_register_spi_devices( master, op->node);
+    }
+
+    return res;
 }
 
 static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op)

^ permalink raw reply

* Re: [PATCH 2/2] uio: add an of_genirq driver
From: Grant Likely @ 2009-06-16 12:46 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: devicetree-discuss, Hans J. Koch, linux-kernel, linuxppc-dev,
	Greg KH
In-Reply-To: <20090616090435.GA21321@pengutronix.de>

On Tue, Jun 16, 2009 at 3:04 AM, Wolfram Sang<w.sang@pengutronix.de> wrote:
>
>> > diff --git a/Documentation/powerpc/dts-bindings/uio-generic.txt b/Docu=
mentation/powerpc/dts-bindings/uio-generic.txt
>> > new file mode 100644
>> > index 0000000..8ad9861
>> > --- /dev/null
>> > +++ b/Documentation/powerpc/dts-bindings/uio-generic.txt
>> > @@ -0,0 +1,16 @@
>> > +UIO for custom devices
>> > +
>> > +A device which will be mapped using the UIO subsystem.
>> > +
>> > +Properties:
>> > + - compatible : should contain the specific model used, followed by
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"generic-uio".
>> > + - reg : address range(s) of the device (up to MAX_UIO_MAPS)
>> > + - interrupts : interrupt of the device
>> > +
>> > +Example:
>> > + =A0 =A0 =A0 =A0c64fpga@0 {
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "ptx,c64fpga001", "gen=
eric-uio";
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0reg =3D <0x0 0x10000>;
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0interrupts =3D <0 0 3>;
>> > + =A0 =A0 =A0 =A0};
>>
>> Hmmm, I'm not happy about this. =A0The device tree describes the
>> hardware, not the way Linux uses the hardware. =A0UIO definitely falls
>> into the category of Linux implementation detail.
>
> Yes, I am aware of that. I just started with the mechanisms which are ava=
ilable
> today and hoped we could find some compatible-value which will suit all n=
eeds.

Trouble is a value that suits all needs today probably won't a year
from now.  :-)

>> This should be approached from the other way around. =A0Either the
>> generic-uio of_platform driver should contain an explicit list of
>> devices to be handled by UIO,
>
> Well, that could lead to a quite huge match_table over time.
>
>> or the OF infrastructure should be modified to allow things like force
>> binding of_devices to of_drivers at runtime.
>
> That is an interesting idea. I could imagine something like a 'new_compat=
ible"
> entry in the sysfs-section of the driver similar to 'new_id' for PCI. Aft=
er
> writing a new compatible-string into it, matching will triggered again wi=
th the
> new entry added. That could (should?) also be placed at the of-core-level=
. Or
> did you have something else in mind?

Yeah, that sounds appropriate.

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH V2 2/2] mtd/maps/mtd-ram: add an of-platform driver
From: Grant Likely @ 2009-06-16 12:53 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: devicetree-discuss, Albrecht Dreß, linuxppc-dev, linux-mtd,
	Ben Dooks, David Woodhouse
In-Reply-To: <20090616091801.GC21321@pengutronix.de>

On Tue, Jun 16, 2009 at 3:18 AM, Wolfram Sang<w.sang@pengutronix.de> wrote:
> On Mon, Jun 15, 2009 at 07:43:20PM +0200, Albrecht Dre=DF wrote:
>> Am 05.06.09 14:05 schrieb(en) Wolfram Sang:
>>> Create an of-aware driver using the now exported generic functions
>>> from plat-ram.c. Also add the documentation for the binding.
>>> Partitions are not yet supported. Tested on a phyCORE-MPC5200B-IO.
>>
>> Dumb question: what is the current status of this patch? =A0I ask becaus=
e
>
> I don't know.
>
> David wondered if 'of_physmap' could be used, so I wrote what I experienc=
ed
> during development. I can't tell if this helped the case.
>
> Grant wondered if we need a bankwidth. IMHO it is needed for now, but I d=
on't
> know if this is a common agreement.

I'm not happy about the use case though.  It probably shouldn't appear
in this binding, or if it does it should be tagged as an optional
property.  It is only in the 5200 localplus case that bank-width is
needed to figure out how to apply the workaround.

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH V2 2/2] mtd/maps/mtd-ram: add an of-platform driver
From: Wolfram Sang @ 2009-06-16 13:20 UTC (permalink / raw)
  To: Grant Likely
  Cc: devicetree-discuss, Albrecht Dreß, linuxppc-dev, linux-mtd,
	Ben Dooks, David Woodhouse
In-Reply-To: <fa686aa40906160553m2f0e7cc4n644c3893573845f@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1051 bytes --]

> > Grant wondered if we need a bankwidth. IMHO it is needed for now, but I don't
> > know if this is a common agreement.
> 
> I'm not happy about the use case though.  It probably shouldn't appear
> in this binding, or if it does it should be tagged as an optional
> property.  It is only in the 5200 localplus case that bank-width is
> needed to figure out how to apply the workaround.

Maybe there is a misunderstanding here. I am not talking about Albrecht's case.
What I replied to your concern is that bankwidth is used(!) in the underlying
map-ram-driver in mapram_erase() at the moment. Whether this is really needed
could be discussed perhaps, but is beyond the scope of this patch series IMHO.
I'd think this can be addressed in a later series, if needed, although this
could mean that the binding will change (bank-width becoming optional).

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH v2] powerpc: 85xx: Add PHY fixup to socrates board code
From: Kumar Gala @ 2009-06-16 13:46 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev
In-Reply-To: <49EE55A4.4000602@denx.de>


On Apr 21, 2009, at 6:24 PM, Anatolij Gustschin wrote:

> Kumar Gala wrote:
>>
>> On Apr 21, 2009, at 4:54 PM, Kumar Gala wrote:
>>
>>>
>>> On Apr 21, 2009, at 12:19 PM, Anatolij Gustschin wrote:
>>>
>>>> If the firmware missed to initialize the PHY correctly,
>>>> Linux may hang up on socrates while eth0/eth1 interface
>>>> startup (caused by continuous unacknowledged PHY interrupt).
>>>>
>>>> This patch adds PHY fixup to socrates platform code to
>>>> ensure the PHY is pre-initialized correctly. It is needed
>>>> to be compatible with older firmware.
>>>>
>>>> Signed-off-by: Anatolij Gustschin <agust@denx.de>
>>>> ---
>>>> Changes since first version:
>>>>    use macros instead of register numbers as
>>>>    suggested by Anton
>>>>
>>>> Kumar, could you please consider this patch for
>>>> inclusion into 2.6.30? Thanks!
>>>
>>> Sorry.  I dont think this is board specific and should at a  
>>> minimum be
>>> done in m88e1011_config_init in drivers/net/phy/marvell.c.  Not sure
>>> how 88E1011 differs from 88E1111, but I'm wondering if you really  
>>> want
>>> to set config_init for m88e1011 to m88e1111_config_init
>>>
>>> - k
>>
>> I got confused by the #'s.. I think we should have a struct in  
>> marvell.c
>> for m88e1121 which I'm guessing is the PHY you are using.
>
> yes, m88e1121 is correct. In 2.6.30-rc2 there is already a m88e1121
> struct in marvell_drivers[] in drivers/net/phy/marvell.c.
> The reason I'm not doing the m88e1121 pre-init stuff in config_init
> is as follows:
>
> m88e1121 is a multi-PHY device with two PHY ports and each port
> could signal an interrupt. This PHY device can be pin-strapped to use
> shared interrupt pin for both PHY ports (as used on socrates board).
> PHY specific config_init will be called e.g. while eth0 startup in
> phy_attach() which is called from phy_connect() in drivers/net/phy/ 
> phy_device.c.
> phy_connect() then calls phy_start_interrupts() which registers the
> interrupt handler and enables the interrupts for the PHY-port  
> config_init
> is called for. Now interrupts can be cleared/acknowledged for this
> PHY-port (eth0 interface), but interrupts from the another PHY-port
> can not be acknowledged as eth1 was not brought up yet.
>
> Placing this fixup in drivers/net/phy/marvell.c as in config_init  
> callback
> could be done, but this will add more overhead as the fixup routine  
> have
> to do more work:
>
> acquire 'struct mii_bus' pointer and walk through all registered PHYs
> searching for the PHY which use the same interrupt, then getting
> the address of this PHY on the bus and disable and clear PHY irqs
> by writing/reading to/from this PHY, (but only in the case it was
> not already brought up and has interrupts enabled!) e.g.:
>
> struct mii_bus *bus = phydev->bus;
> int addr;
>
> for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
> 	struct phy_device *phy = bus->phy_map[addr];
>
> 	if (addr != phydev->addr && bus->irq[addr] == phydev->irq &&
> 	    (phy->phy_id & 0x0ffffff0) == 0x01410cb0 &&
> 	    !(phy->interrupts & PHY_INTERRUPT_ENABLED)) {
>
> 		int imask = phy_read(phy, MII_M1011_IMASK);
>
> 		if (imask) {
> 			phy_write(phy, 0x12, 0); /* disable */
> 			phy_read(phy, 0x13); /* clear */
> 		}
> 	}
> }
>
> All this to allow support for multiple m88e1121 devices.
> Otherwise, after registering first phy interrupt handler
> and enabling interrupt pending irq on other PHY port or
> other PHY device will lock up the board.
>
> The fixup in this patch will only be done while mdio bus scan
> before registering a PHY device.

Did we ever resolve this?

- k

^ permalink raw reply

* PowerPC PCI DMA issues (prefetch/coherency?)
From: Chris Pringle @ 2009-06-16 14:08 UTC (permalink / raw)
  To: linuxppc-dev

Hello All,

We're developing on a Freescale MPC8272 and are having some nasty 
problems with PCI bus mastering and data corruption.

We have some custom hardware that is bus mastering, reading data from 
the CPUs memory for it's own use. Most of the time, the data is correct, 
however occasionally we are seeing data that appears to be from 
somewhere else in memory (usually memory that has already been read by 
the PCI device). The problem looks like stale data on the PCI bridge 
prefetch buffers or a cache coherency problem, but we've been unable to 
come up with a solution to our problem. It is my understanding that it 
shouldn't be a cache coherency problem as the CPU cache should be 
snooped as the data is read from memory. Even if it were an issue, the 
pci_map_sg* functions should have sorted out any cache coherency issues 
before the DMA operation started.

I've not been able to find anything on the Freescale data sheet that 
provides any way of flushing the prefetch cache on the PCI bridge. We've 
done a bit of experimenting, and found that turning off prefetch appears 
to solve (or possibly mask?) the problem (at the expensive of massive 
performance problems). I've also tried DMA'ing two adjacent userspace 
buffers in memory (from the same page), and see corruption on the second 
buffer. If I populate both buffers, then DMA them both, the data is 
fine. If I populate the first, DMA the first, then populate the second 
and DMA the second, corruption occurs at the start of the second buffer. 
If I add 8-32 bytes of padding between the buffers, the problem goes away.

The PCI spec says that the PCI bridge is supposed to flush any data from 
it's prefetch buffers that are not read by the bus master, so 
technically, this isn't supposed to happen.

I've tried making sure that buffers are cache line (and page) aligned, 
and are multiples of cache lines, but it's made no difference. PIO mode 
works fine, and I've checked the data with the CPU just before, and 
immediately after the DMA and the driver sees no data integrity issues. 
There are memory write barriers just before the DMA start, so all the 
registers should be correct before the DMA starts.

For background info, the device doing the bus mastering is a Xilinx 
Virtex 5 FPGA. We've monitored the data as it comes off the PCI bus 
using ChipScope - so the firmware should not be manipulating the data in 
any way.

We have some hardware/firmware/drivers that has a lot of common code 
that runs on an x86 platform (as opposed to powerpc), and that works 
without any issues whatsoever.

Has anyone got any ideas what this might be? Does anyone of know issues 
with PCI bridges on the PowerPC platform? Is there extra things that 
need to be done from the driver when DMAing on PowerPC (I've looked at 
other drivers and there's nothing obvious). The chip errata doesn't have 
anything on it that looks like it could cause this.

I'm really hoping this is something that we're doing wrong in the driver 
or the firmware, but we've been through both the firmware and drivers 
countless times and are unable to see anything wrong.

Any thoughts/ideas would be much appreciated!

Regards,
Chris

-- 

______________________________
Chris Pringle
Software Engineer

Miranda Technologies Ltd.
Hithercroft Road
Wallingford
Oxfordshire OX10 9DG
UK

Tel. +44 1491 820206
Fax. +44 1491 820001
www.miranda.com

____________________________

Miranda Technologies Limited
Registered in England and Wales CN 02017053
Registered Office: James House, Mere Park, Dedmere Road, Marlow, Bucks, SL7 1FJ

^ permalink raw reply

* Re: [PATCH] RFC: powerpc: expose the multi-bit ops that underlie single-bit ops.
From: Geoff Thorpe @ 2009-06-16 14:28 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1245124418.12400.67.camel@pasglop>

Thanks for taking the time to look at this Ben, comments inline.

Benjamin Herrenschmidt wrote:
> On Tue, 2009-05-26 at 14:19 -0400, Geoff Thorpe wrote:
>> NOT FOR COMMIT, THIS IS A REQUEST FOR FEEDBACK.
>>
>> The bitops.h functions that operate on a single bit in a bitfield are
>> implemented by operating on the corresponding word location. In all cases
>> the inner logic appears to be valid if the mask being applied has more
>> than one bit set, so this patch exposes those inner operations. Indeed,
>> set_bits() was already available, but it duplicated code from set_bit()
>> (rather than making the latter a wrapper) - it was also missing the
>> PPC405_ERR77() workaround and the "volatile" address qualifier present in
>> other APIs. This corrects that, and exposes the other multi-bit
>> equivalents.
>>
>> One advantage of these multi-bit forms is that they allow word-sized
>> variables to essentially be their own spinlocks.
> 
> Hi ! Sorry for the delay, that was on my "have a look one of these days,
> low priority" list for a bit too long :-)

NP, optimal throughput often requires a compromise in latency :-)

> 
>> NB, the same factoring is possible in asm-generic/bitops/[non-]atomic.h.
>> I would be happy to provide corresponding patches if this approach is
>> deemed appropriate. Feedback would be most welcome.
>>
>> Signed-off-by: Geoff Thorpe <Geoff.Thorpe@freescale.com>
>> ---
>>  arch/powerpc/include/asm/bitops.h |  111 +++++++++++++++++++++++--------------
>>  1 files changed, 69 insertions(+), 42 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
>> index 897eade..72de28c 100644
>> --- a/arch/powerpc/include/asm/bitops.h
>> +++ b/arch/powerpc/include/asm/bitops.h
>> @@ -56,11 +56,10 @@
>>  #define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
>>  #define BITOP_LE_SWIZZLE	((BITS_PER_LONG-1) & ~0x7)
>>  
>> -static __inline__ void set_bit(int nr, volatile unsigned long *addr)
>> +static __inline__ void set_bits(unsigned long mask, volatile unsigned long *_p)
>>  {
>>  	unsigned long old;
>> -	unsigned long mask = BITOP_MASK(nr);
>> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
>> +	unsigned long *p = (unsigned long *)_p;
>>  
>>  	__asm__ __volatile__(
>>  "1:"	PPC_LLARX "%0,0,%3	# set_bit\n"
>> @@ -73,11 +72,16 @@ static __inline__ void set_bit(int nr, volatile unsigned long *addr)
>>  	: "cc" );
>>  }
>>  
>> -static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
>> +static __inline__ void set_bit(int nr, volatile unsigned long *addr)
>> +{
>> +	set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
>> +}
> 
> No objection with the above.
> 
>> +static __inline__ void clear_bits(unsigned long mask,
>> +				volatile unsigned long *_p)
>>  {
>>  	unsigned long old;
>> -	unsigned long mask = BITOP_MASK(nr);
>> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
>> +	unsigned long *p = (unsigned long *)_p;
>>  
>>  	__asm__ __volatile__(
>>  "1:"	PPC_LLARX "%0,0,%3	# clear_bit\n"
>> @@ -90,11 +94,16 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
>>  	: "cc" );
>>  }
>>  
>> -static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
>> +static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
>> +{
>> +	clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
>> +}
> 
> Looks good too.
> 
>> +static __inline__ void clear_bits_unlock(unsigned long mask,
>> +					volatile unsigned long *_p)
>>  {
>>  	unsigned long old;
>> -	unsigned long mask = BITOP_MASK(nr);
>> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
>> +	unsigned long *p = (unsigned long *)_p;
>>  
>>  	__asm__ __volatile__(
>>  	LWSYNC_ON_SMP
>> @@ -108,11 +117,16 @@ static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
>>  	: "cc", "memory");
>>  }
>>  
>> -static __inline__ void change_bit(int nr, volatile unsigned long *addr)
>> +static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
>> +{
>> +	clear_bits_unlock(BITOP_MASK(nr), addr + BITOP_WORD(nr));
>> +}
> 
> I'm not sure it's useful to provide a multi-bit variant of the
> "lock" and "unlock" primitives. Do other archs do ?

For clear_bit_unlock(), no they don't appear to. There is a fallback in
include/asm-generic though, and I notice that it's used in a few places,
eg. drivers/rtc/rtc-dev. OTOH some other archs appear to provide their
own test_and_set_bit_lock(), and there's a fallback in
includes/asm-generic for that too.

Do you see a reason to isolate either of these and not factor out the
inner word-based logic?

> 
>> +static __inline__ void change_bits(unsigned long mask,
>> +				volatile unsigned long *_p)
>>  {
>>  	unsigned long old;
>> -	unsigned long mask = BITOP_MASK(nr);
>> -	unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
>> +	unsigned long *p = (unsigned long *)_p;
>>  
>>  	__asm__ __volatile__(
>>  "1:"	PPC_LLARX "%0,0,%3	# change_bit\n"
>> @@ -125,12 +139,16 @@ static __inline__ void change_bit(int nr, volatile unsigned long *addr)
>>  	: "cc" );
>>  }
>>  
>> -static __inline__ int test_and_set_bit(unsigned long nr,
>> -				       volatile unsigned long *addr)
>> +static __inline__ void change_bit(int nr, volatile unsigned long *addr)
>> +{
>> +	change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
>> +}
> 
> Ah, patch is getting confused between change_bit and
> test_and_set_bit :-)

The diff machinery off-by-one'd the entire file, which makes the patch a
little more difficult to review. But I didn't feel like (further)
massacring the code in order to improve the diff. :-)

> 
> Now, you know what I'm thinking is ... Those are all the same except
> for:
> 
>  - Barriers for lock and unlock variants
>  - Barriers for "return" (aka test_and_set) variants
>  - Actual op done on the mask

Yup, believe it or not, I saw this coming but didn't have the guts to
try proposing something like it up-front (in particular, I was wary of
botching some subtleties in the assembly).

> 
> Maybe we can shrink that file significantly (and avoid the risk for
> typos etc...) by generating them all from a macro.
> 
> Something like (typed directly into the mailer :-)
> 
> #define DEFINE_BITOP(op, prefix, postfix) \
> 	asm volatile (			  \
> 	prefix				  \
> "1:"    PPC_LLARX "%0,0,%3\n"		  \
> 	__stringify(op) "%1,%0,%2\n"	  \
> 	PPC405_ERR77(0,%3)		  \
> 	PPC_STLCX "%1,0,%3\n"		  \
> 	"bne- 1b\n"			  \
> 	postfix				  \
> 	 : "=&r" (old), "=&r" (t)
> 	 : "r" (mask), "r" (p)
> 	 : "cc", "memory")
> 
> and so:
> 
> static inline void set_bits(unsigned long mask, volatile unsigned long *addr)
> {
> 	unsigned long old, t;
> 
> 	DEFINE_BITOP(or, "", "");
> }
> 
> static inline void test_and_set_bits(unsigned long mask, volatile unsigned long *addr)
> {
> 	unsigned long old, t;
> 
> 	DEFINE_BITOP(or, LWSYNC_ON_SMP, ISYNC_ON_SMP);
> 
> 	return (old & mask) != 0;
> }
> 
> etc...


Sounds good, I'll try working this up and I'll send a new patch shortly.

So can I assume implicitly that changing the set_bits() function to add
the 'volatile' qualifier to the prototype (and the missing
PPC405_ERR77() workaround) was OK?

Also - any opinion on whether the same re-factoring of the asm-generic
versions should be undertaken? I'm not looking to bite off more than I
can chew, but I don't know if it's frowned upon to make powerpc-only
extensions to the API. And if you think an asm-generic patch makes
sense, could that be taken via linuxppc-dev too or does it need to go
elsewhere?

Thanks again,
Geoff

^ permalink raw reply

* [PATCH] powerpc: Update Warp defconfig
From: Sean MacLennan @ 2009-06-16 15:24 UTC (permalink / raw)
  To: linuxppc-dev, Josh Boyer

I forgot to include the defconfig in the last set of patches. So you
don't get to use the shiny new LEDS driver on the warp unless you turn
it on.

Enabling hotplug is also very important since we have moved to udev on
the warp.

Like most defconfig patches, most of the changes are just the normal
kernel changes, not warp specific.

If it is too early, and we want to hold off until say rc4 with
defconfigs I have no problem with that. I have tried to outline all the
changes we specifically made. If anybody sees any bad choices with
options, let me know!

Cheers,
   Sean

* Enable GPIO LEDS
* Enable LED triggers
* Move to slub
* Enable hotplug
* Enable timestamps on printks
* Enable UBIFS

Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
---
diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig
index 3b77f09..787635f 100644
--- a/arch/powerpc/configs/44x/warp_defconfig
+++ b/arch/powerpc/configs/44x/warp_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Fri Jan 23 07:57:16 2009
+# Linux kernel version: 2.6.30
+# Tue Jun  9 23:35:36 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -41,6 +41,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -53,10 +54,12 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_PPC_DCR_NATIVE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_DCR=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -74,7 +77,17 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
@@ -82,27 +95,29 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -110,10 +125,13 @@ CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -121,6 +139,7 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -133,7 +152,6 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -149,11 +167,6 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -173,10 +186,11 @@ CONFIG_WARP=y
 # CONFIG_ARCHES is not set
 # CONFIG_CANYONLANDS is not set
 # CONFIG_GLACIER is not set
+# CONFIG_REDWOOD is not set
 # CONFIG_YOSEMITE is not set
 # CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set
 # CONFIG_PPC44x_SIMPLE is not set
-# CONFIG_PPC4xx_GPIO is not set
+CONFIG_PPC4xx_GPIO=y
 CONFIG_440EP=y
 CONFIG_IBM440EP_ERR42=y
 # CONFIG_IPIC is not set
@@ -235,9 +249,13 @@ CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_STDBINUTILS=y
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_PROC_DEVICETREE=y
 CONFIG_CMDLINE_BOOL=y
@@ -256,6 +274,7 @@ CONFIG_PPC_PCI_CHOICE=y
 # CONFIG_PCI_DOMAINS is not set
 # CONFIG_PCI_SYSCALL is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
 # CONFIG_HAS_RAPIDIO is not set
 
 #
@@ -271,14 +290,12 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
-CONFIG_CONSISTENT_START=0xff100000
 CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -353,6 +370,7 @@ CONFIG_VLAN_8021Q=y
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -365,7 +383,6 @@ CONFIG_VLAN_8021Q=y
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
@@ -378,8 +395,12 @@ CONFIG_VLAN_8021Q=y
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_STANDALONE is not set
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -471,13 +492,21 @@ CONFIG_MTD_NAND_NDFC=y
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
 #
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
@@ -495,10 +524,17 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_XILINX_SYSACE is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -529,7 +565,7 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
-CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_SCSI_WAIT_SCAN is not set
 
 #
 # SCSI Transports
@@ -541,10 +577,12 @@ CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_SRP_ATTRS is not set
 # CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -554,6 +592,8 @@ CONFIG_NETDEVICES=y
 # CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 CONFIG_IBM_NEW_EMAC=y
 CONFIG_IBM_NEW_EMAC_RXB=128
 CONFIG_IBM_NEW_EMAC_TXB=64
@@ -577,7 +617,6 @@ CONFIG_IBM_NEW_EMAC_ZMII=y
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -646,6 +685,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_HVC_UDBG is not set
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
@@ -663,6 +703,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_GPIO is not set
 CONFIG_I2C_IBM_IIC=y
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_OCORES is not set
@@ -685,12 +726,9 @@ CONFIG_I2C_IBM_IIC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-CONFIG_EEPROM_AT24=y
-CONFIG_EEPROM_LEGACY=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -699,7 +737,30 @@ CONFIG_EEPROM_LEGACY=y
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
@@ -721,6 +782,7 @@ CONFIG_SENSORS_AD7414=y
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -735,11 +797,15 @@ CONFIG_SENSORS_AD7414=y
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
 # CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
@@ -785,6 +851,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
@@ -870,11 +937,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -915,7 +982,6 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -929,6 +995,8 @@ CONFIG_USB_STORAGE=y
 #
 # OTG and related infrastructure
 #
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
@@ -946,6 +1014,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y
 #
 # CONFIG_MMC_SDHCI is not set
 # CONFIG_MMC_WBSD is not set
+CONFIG_MMC_PIKASD=y
 # CONFIG_MEMSTICK is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -953,16 +1022,31 @@ CONFIG_LEDS_CLASS=y
 #
 # LED drivers
 #
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_GPIO_PLATFORM is not set
+CONFIG_LEDS_GPIO_OF=y
+# CONFIG_LEDS_LP5521 is not set
 # CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
 
 #
 # LED Triggers
 #
-# CONFIG_LEDS_TRIGGERS is not set
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_EDAC is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -973,6 +1057,7 @@ CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 # CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
@@ -993,6 +1078,11 @@ CONFIG_INOTIFY_USER=y
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1039,6 +1129,12 @@ CONFIG_JFFS2_ZLIB=y
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
 CONFIG_CRAMFS=y
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1049,6 +1145,7 @@ CONFIG_CRAMFS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1060,7 +1157,6 @@ CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1115,6 +1211,7 @@ CONFIG_NLS_ISO8859_15=y
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=y
 # CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1122,7 +1219,7 @@ CONFIG_NLS_UTF8=y
 CONFIG_BITREVERSE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=y
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 CONFIG_CRC_T10DIF=y
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
@@ -1130,16 +1227,19 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
 
 #
 # Kernel hacking
 #
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
@@ -1152,11 +1252,15 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1180,9 +1284,12 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -1190,24 +1297,27 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
 # CONFIG_XMON is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_VIRQ_DEBUG is not set
-CONFIG_BDI_SWITCH=y
+# CONFIG_BDI_SWITCH is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1223,6 +1333,8 @@ CONFIG_CRYPTO=y
 # Crypto core or helper
 #
 # CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
 # CONFIG_CRYPTO_MANAGER is not set
 # CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
@@ -1294,13 +1406,15 @@ CONFIG_CRYPTO=y
 #
 # Compression
 #
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
 
 #
 # Random Number Generation
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_PPC4XX is not set
 # CONFIG_PPC_CLOCK is not set
 # CONFIG_VIRTUALIZATION is not set

^ permalink raw reply related

* Re: [PATCH V2 2/2] mtd/maps/mtd-ram: add an of-platform driver
From: Grant Likely @ 2009-06-16 15:34 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: devicetree-discuss, Albrecht Dreß, linuxppc-dev, linux-mtd,
	Ben Dooks, David Woodhouse
In-Reply-To: <fa686aa40906160833g1d77466ekf8b8d4350ab32a24@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1054 bytes --]

Okay, fair enough.  I wasn't paying very close attention when I replied.  It
still seems awkward to me, but not enough to object (ie. It's not
dangerous).

g.

On Jun 16, 2009 7:20 AM, "Wolfram Sang" <w.sang@pengutronix.de> wrote:

> > Grant wondered if we need a bankwidth. IMHO it is needed for now, but I
don't > > know if this i...
Maybe there is a misunderstanding here. I am not talking about Albrecht's
case.
What I replied to your concern is that bankwidth is used(!) in the
underlying
map-ram-driver in mapram_erase() at the moment. Whether this is really
needed
could be discussed perhaps, but is beyond the scope of this patch series
IMHO.
I'd think this can be addressed in a later series, if needed, although this
could mean that the binding will change (bank-width becoming optional).

Regards, Wolfram -- Pengutronix e.K. | Wolfram Sang ...

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAko3nAUACgkQD27XaX1/VRtTkACfW0aUMJHrU3m4DCel0pm5fA6J
WaQAnjGo5fn6JvMHt3Ke/xFTGB1uYT6p
=V9t5
-----END PGP SIGNATURE-----

[-- Attachment #2: Type: text/html, Size: 1407 bytes --]

^ permalink raw reply

* Re: PowerPC PCI DMA issues (prefetch/coherency?)
From: Roderick Colenbrander @ 2009-06-16 15:48 UTC (permalink / raw)
  To: Chris Pringle; +Cc: linuxppc-dev
In-Reply-To: <4A37A740.1090501@oxtel.com>

Hi Chris,

The last couple of months I had the 'pleasure' to work with a Xilinx
ML510 ATX board which contains a Virtex-5 FXT. In my case I had to set
up the plbv46 pci soft-core to function properly with PCI add-on
boards and onboard pci devices. I have had a lot of issues including
ones with DMA but in the end it worked properly. I'm not sure how in
your case the Virtex-5 is wired to the PCI bus but in my case it was
connected to the crossbar switch of the PowerPC 440 which is inside
the Virtex-5 FXT. Not all Xilinx reference designs were interfaced
properly to this (sometimes the MPLB->SPLB connection from the
soft-core to the crossbar wasn't connected) and even then the PCI
soft-core wasn't configured properly by Xilinx and this MIGHT be
similar to your issue.

In the explanation of the issue I will use the terminology used by
Xilinx. The CPU side is the 'IPIF' side and the and the PCI side is
the 'PCI' side. Both domains have their own address domains and hence
translation from IPIFtoPCI and PCItoIPIF is needed. From what I
understood is that the 'incoming window' (ipif->pci) and outgoing
window (pci>ipif) should use different address ranges else the bridge
gets confused. I don't have access to my design right now but by head
Xilinx doesn't set C_IPIFBAR2PCIBAR_0 properly in a lot of cases and
just sets it to 0. Which means that cpu -> ipif (lets say the soft
core is accessible from 0xa0000000 from the cpu) 0xa0001234 translates
to 0x00001234 on the PCI side but PCI cards expect that when they
write low memory addresses that they write to system memory. What
should be done is to set C_IPIFBAR2PCIBAR_0 to 0xa0000000 in this
case, so that the incoming window is 0xa0000000-0xffffffff
and the outgoing window 0x00000000-0x9fffffff or just set it half way
at 0x80000000.

I'm not saying this is your issue but it could be it.

Regards,
Roderick Colenbrander


On Tue, Jun 16, 2009 at 4:08 PM, Chris Pringle<chris.pringle@oxtel.com> wrote:
> Hello All
>
> We're developing on a Freescale MPC8272 and are having some nasty problems
> with PCI bus mastering and data corruption.
>
> We have some custom hardware that is bus mastering, reading data from the
> CPUs memory for it's own use. Most of the time, the data is correct, however
> occasionally we are seeing data that appears to be from somewhere else in
> memory (usually memory that has already been read by the PCI device). The
> problem looks like stale data on the PCI bridge prefetch buffers or a cache
> coherency problem, but we've been unable to come up with a solution to our
> problem. It is my understanding that it shouldn't be a cache coherency
> problem as the CPU cache should be snooped as the data is read from memory.
> Even if it were an issue, the pci_map_sg* functions should have sorted out
> any cache coherency issues before the DMA operation started.
>
> I've not been able to find anything on the Freescale data sheet that
> provides any way of flushing the prefetch cache on the PCI bridge. We've
> done a bit of experimenting, and found that turning off prefetch appears to
> solve (or possibly mask?) the problem (at the expensive of massive
> performance problems). I've also tried DMA'ing two adjacent userspace
> buffers in memory (from the same page), and see corruption on the second
> buffer. If I populate both buffers, then DMA them both, the data is fine. If
> I populate the first, DMA the first, then populate the second and DMA the
> second, corruption occurs at the start of the second buffer. If I add 8-32
> bytes of padding between the buffers, the problem goes away.
>
> The PCI spec says that the PCI bridge is supposed to flush any data from
> it's prefetch buffers that are not read by the bus master, so technically,
> this isn't supposed to happen.
>
> I've tried making sure that buffers are cache line (and page) aligned, and
> are multiples of cache lines, but it's made no difference. PIO mode works
> fine, and I've checked the data with the CPU just before, and immediately
> after the DMA and the driver sees no data integrity issues. There are memory
> write barriers just before the DMA start, so all the registers should be
> correct before the DMA starts.
>
> For background info, the device doing the bus mastering is a Xilinx Virtex 5
> FPGA. We've monitored the data as it comes off the PCI bus using ChipScope -
> so the firmware should not be manipulating the data in any way.
>
> We have some hardware/firmware/drivers that has a lot of common code that
> runs on an x86 platform (as opposed to powerpc), and that works without any
> issues whatsoever.
>
> Has anyone got any ideas what this might be? Does anyone of know issues with
> PCI bridges on the PowerPC platform? Is there extra things that need to be
> done from the driver when DMAing on PowerPC (I've looked at other drivers
> and there's nothing obvious). The chip errata doesn't have anything on it
> that looks like it could cause this.
>
> I'm really hoping this is something that we're doing wrong in the driver or
> the firmware, but we've been through both the firmware and drivers countless
> times and are unable to see anything wrong.
>
> Any thoughts/ideas would be much appreciated!
>
> Regards,
> Chris
>
> --
>
> ______________________________
> Chris Pringle
> Software Engineer
>
> Miranda Technologies Ltd.
> Hithercroft Road
> Wallingford
> Oxfordshire OX10 9DG
> UK
>
> Tel. +44 1491 820206
> Fax. +44 1491 820001
> www.miranda.com
>
> ____________________________
>
> Miranda Technologies Limited
> Registered in England and Wales CN 02017053
> Registered Office: James House, Mere Park, Dedmere Road, Marlow, Bucks, SL7
> 1FJ
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>

^ permalink raw reply

* Re: [ewg] Re: [PATCH 2.6.31] ehca: Tolerate dynamic memory operations and huge pages
From: Roland Dreier @ 2009-06-16 16:10 UTC (permalink / raw)
  To: Alexander Schmidt
  Cc: linuxppc-dev, Hoang-Nam Nguyen, raisch, linux-kernel, ewg
In-Reply-To: <20090616090809.34d162fc@BL3D1974.boeblingen.de.ibm.com>


 > Yeah, the notifier code remains untouched as we still do not allow dynamic
 > memory operations _while_ our module is loaded. The patch allows the driver to
 > cope with DMEM operations that happened before the module was loaded, which
 > might result in a non-contiguous memory layout. When the driver registers
 > its global memory region in the system, the memory layout must be considered.
 > 
 > We chose the term "toleration" instead of "support" to illustrate this.

I see.  So things just silently broke in some cases when the driver was
loaded after operations you didn't tolerate?

Anyway, thanks for the explanation.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox