LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Sergei Shtylyov @ 2007-06-04 15:54 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, linux-mtd, Milton Miller
In-Reply-To: <f24cbe6245fb2a52d153edb9be678f5a@kernel.crashing.org>

Segher Boessenkool wrote:

>>> You make no sense to me. It's like saying that knowing that a 8250 chip
>>> on ISA cannot be accessed if you don't know it's IO ports so it
>>> shouldn't say "8250" in compatible property ?!?!?!?

>>    No, it's a completely different case.  Base address and even flash 
>> size are not the only things that matter.  There's bus width

> Bus width is an (inherent) property of the _parent_
> node.  Device width is normally equal to that, and
> if not, it is obvious from the device model.

    Eh... obvious? From the bus controller node? Maybe and maybe not. Those 
are seem to be generally multifuntional and so don't have their "chip selects" 
fixed to some kind of interface, i.e. it's selectable, as well as the bus 
width even... at least it's so in my case (and nevertheless, the board has 
interleaved flash, so it's not a matter of a bus width fixed to 32 bits as you 
can see).

> Also, you need to know if the devices are byte-addressable
> or only per natural unit; and even more importantly,
> the same question for the flash bus.

>> and interleave factors

> Not a property of the flash chips really.

    Who said it is?

>> that influence the access (and possibly, byte-swapping too, although 
>> this is unlikely to happen in PPC world).

> Byte swapping?  1) This should _never_ be necessary,
> just swap the data on the device itself, duh;

    Oh, I'm afraid that's only wishful thinking after having some real life 
experience in bi-endian world.  Luckily, the PPC world seems to be (at least 
mostly) big-endian.

> 2) more likely this would be determined by the flash bus, not
> per flash device.

    Indeed, by wiring the bus pins to flash pins. :-)

> And, 3) why would you want to include this in the flash
> binding while we don't yet have a reasonable overview
> of in what circumstances byte swap is needed/used?

    This was just a real world example. I do hope PPC would never have to deal 
with it, though...

>>> Also, whatever shortcomings of the linux MTD drivers are totally
>>> irrelevant to what is correct to have in a device-tree. While we do
>>> tailor our device-tree specification around linux needs in most cases,
>>> there are cases like this one where common sense should be enough to
>>> understand that it's not because the linux MTD subsystem, as of today,
>>> cannot be told what programming interface to use, that we shouldn't
>>> provide that information in the tree.

>>    We did provide it, in the form of probing hints ("probe-type" prop).

> Which is 103% redundant.  That same information (and
> more!) is required in the "compatible" property, already.

    Yeah, but then we would have needed more than one node -- which I avoided 
back then... well, I have cheated and mistaken. :-)
    Anyway, the "rom" device node as it appeared in booting-without-of.txt
was based upon suggestions from Linux/MTD maintainer.

> Segher

WBR, Sergei

^ permalink raw reply

* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Segher Boessenkool @ 2007-06-04 14:49 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linuxppc-dev, linux-mtd, Milton Miller
In-Reply-To: <46640892.2030408@ru.mvista.com>

>> You make no sense to me. It's like saying that knowing that a 8250 
>> chip
>> on ISA cannot be accessed if you don't know it's IO ports so it
>> shouldn't say "8250" in compatible property ?!?!?!?
>
>    No, it's a completely different case.  Base address and even flash 
> size are not the only things that matter.  There's bus width

Bus width is an (inherent) property of the _parent_
node.  Device width is normally equal to that, and
if not, it is obvious from the device model.

Also, you need to know if the devices are byte-addressable
or only per natural unit; and even more importantly,
the same question for the flash bus.

> and interleave factors

Not a property of the flash chips really.

> that influence the access (and possibly, byte-swapping too, although 
> this is unlikely to happen in PPC world).

Byte swapping?  1) This should _never_ be necessary,
just swap the data on the device itself, duh; 2) more
likely this would be determined by the flash bus, not
per flash device.

And, 3) why would you want to include this in the flash
binding while we don't yet have a reasonable overview
of in what circumstances byte swap is needed/used?

>> Also, whatever shortcomings of the linux MTD drivers are totally
>> irrelevant to what is correct to have in a device-tree. While we do
>> tailor our device-tree specification around linux needs in most cases,
>> there are cases like this one where common sense should be enough to
>> understand that it's not because the linux MTD subsystem, as of today,
>> cannot be told what programming interface to use, that we shouldn't
>> provide that information in the tree.
>
>    We did provide it, in the form of probing hints ("probe-type" prop).

Which is 103% redundant.  That same information (and
more!) is required in the "compatible" property, already.


Segher

^ permalink raw reply

* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Sergei Shtylyov @ 2007-06-04 14:49 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: ppcdev, linux-mtd, Milton Miller
In-Reply-To: <879d8eb0b405619a9e457d137c27baa2@kernel.crashing.org>

Segher Boessenkool wrote:

>>> So you are saying that because the current linux MTD stuff can only
>>> probe (which doesn't always work), we should not put the proper chip
>>> interface type in the device-tree ?

>>    No. But if/when we put it, it'll only be able to influence 
>> interface probing, but not "force" the interface.

> Of course it can; that just means you have to fix MTD

    I wouldn't call this a fix, more like an additional feature. Probing has 
worked well enough.

> and/or the way your platform calls MTD.

    The platform code is not supposed to call MTD *at all*. The only expeption
so far are physmap_configure() and physmap_set_partitions() which are both 
considered obsolete (in favor of platform device). Maybe linux-mtd people will 
correct me though...

>>    The money was not the only factor, you know, I was under the 
>> pressure of schedules, and had a lot more things to do.

> The bigger Linux community does not (and should not)
> care about your corporate schedules.  Your patches
> won't be merged upstream until they are deemed to be
> of acceptable quality.  If that doesn't fit your
> employer's schedule, well tough luck, they can maintain
> their own kernel fork I'm sure?

    But the driver have been nevertheless merged. Moreover, the it was one of 
the MTD maintainers who expressed desire for partition info to be kept with 
device node in the first place.

> Segher

WBR, Sergei

^ permalink raw reply

* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Segher Boessenkool @ 2007-06-04 14:37 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: ppcdev, linux-mtd, Milton Miller
In-Reply-To: <466406BB.3070607@ru.mvista.com>

>> So you are saying that because the current linux MTD stuff can only
>> probe (which doesn't always work), we should not put the proper chip
>> interface type in the device-tree ?
>
>    No. But if/when we put it, it'll only be able to influence 
> interface probing, but not "force" the interface.

Of course it can; that just means you have to fix MTD
and/or the way your platform calls MTD.

>    The money was not the only factor, you know, I was under the 
> pressure of schedules, and had a lot more things to do.

The bigger Linux community does not (and should not)
care about your corporate schedules.  Your patches
won't be merged upstream until they are deemed to be
of acceptable quality.  If that doesn't fit your
employer's schedule, well tough luck, they can maintain
their own kernel fork I'm sure?


Segher

^ permalink raw reply

* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Sergei Shtylyov @ 2007-06-04 13:34 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, linux-mtd, Milton Miller
In-Reply-To: <193459b778ff98aa95ee7ac38a842c16@kernel.crashing.org>

Hello.

Segher Boessenkool wrote:

>>>>> This has nothing to do with a "chip level", it is plain and
>>>>> simply the most basic device tree stuff.

>>>>    If it was as "plain and simple" as you say, there would be 
>>>> nothing to argue about.

>>> There isn't as far as I am concerned; the purpose and
>>> meaning of the "compatible" property, as well as of any
>>> other standard OF properties, is clear.

>>    Erm, concerning matching those with drivers it wasn't as clear that 
>> those props aren't the same as driver names b/c of the follwing 
>> passage in Generic Names:

> [huge snip]

> Please point out the exact passage you don't understand, and
> what you don't understand about it, if you want any help.

    Ah, nevermind... It was too late in the Sunday evening. :-)

>>> Yes, the more complex (and sometimes insane) ways that
>>> flash chips are connected to systems can be really hard
>>> to describe properly.  Which is why I don't even want
>>> to make a "binding" for it (yet).  It seems easy enough

>>    Neither do we. :-)

>>> to do this for single flash chips (possibly direct-mapped)
>>> though.

>>    Erm, FSL boards seem to generally have dual 16-bit NOR flash chips 
>> interleaved -- and that's seems quite a common case, not only in PPC 
>> world.

> It's not all that common; I can see why it would be used on
> flash controllers that handle a 32-bit bus only.

    OK, maybe it's just we, embedded guys, that comes to see only such cheapo 
boards. :-)

>>    Perhaps... those interleaved chips could really be merged 
>> (abstracted) into a single one, with the bus width being a sum of two?

> Perhaps.  It is a nasty situation, it'll take long hard
> thinking to come up with a reasonably good solution.

    I hoped to get some hints from the linux-mtd list as well...

>>>  Get the simple cases
>>> (that actually are used in real life) right, first.

>>    We pursued this task exactly. Get it working, quick. :-)

> That is something *TOTALLY DIFFERENT* and quite a bad plan
> IMNSHO.

    I haven't considered 2 inteleaved 16-bit CFI NOR flashes a complex case so 
far, sorry. :-) And that's what I had on my board. Prior to my acquaintance 
with the device trees, this was indeed a no-brainer. :-)

> Segher

WBR, Sergei

^ permalink raw reply

* [PATCH 5/6] spufs: synchronize pte invalidation vs ps close
From: Jeremy Kerr @ 2007-06-04 13:26 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, cbe-oss-dev

From: Christoph Hellwig <hch@lst.de>

Make sure the mapping_lock also protects access to the various address_space
pointers used for tearing down the ptes on a spu context switch.

Because unmap_mapping_range can sleep we need to turn mapping_lock from
a spinlock into a sleeping mutex.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 8654749..7c51cb5 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -39,7 +39,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
 	if (spu_init_csa(&ctx->csa))
 		goto out_free;
 	spin_lock_init(&ctx->mmio_lock);
-	spin_lock_init(&ctx->mapping_lock);
+	mutex_init(&ctx->mapping_lock);
 	kref_init(&ctx->kref);
 	mutex_init(&ctx->state_mutex);
 	mutex_init(&ctx->run_mutex);
@@ -103,6 +103,7 @@ void spu_forget(struct spu_context *ctx)
 
 void spu_unmap_mappings(struct spu_context *ctx)
 {
+	mutex_lock(&ctx->mapping_lock);
 	if (ctx->local_store)
 		unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
 	if (ctx->mfc)
@@ -117,6 +118,7 @@ void spu_unmap_mappings(struct spu_context *ctx)
 		unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
 	if (ctx->psmap)
 		unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
+	mutex_unlock(&ctx->mapping_lock);
 }
 
 /**
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 89a5011..b1e7e2f 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -45,11 +45,11 @@ spufs_mem_open(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->local_store = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -59,10 +59,10 @@ spufs_mem_release(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->local_store = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -310,11 +310,11 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->cntl = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return simple_attr_open(inode, file, spufs_cntl_get,
 					spufs_cntl_set, "0x%08lx");
 }
@@ -327,10 +327,10 @@ spufs_cntl_release(struct inode *inode, struct file *file)
 
 	simple_attr_close(inode, file);
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->cntl = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -813,11 +813,11 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->signal1 = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -827,10 +827,10 @@ spufs_signal1_release(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->signal1 = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -937,11 +937,11 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->signal2 = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -951,10 +951,10 @@ spufs_signal2_release(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->signal2 = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -1155,10 +1155,10 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
 
 	file->private_data = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!i->i_openers++)
 		ctx->mss = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -1168,10 +1168,10 @@ spufs_mss_release(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->mss = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -1212,11 +1212,11 @@ static int spufs_psmap_open(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = i->i_ctx;
 	if (!i->i_openers++)
 		ctx->psmap = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -1226,10 +1226,10 @@ spufs_psmap_release(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->psmap = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
@@ -1282,11 +1282,11 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
 	if (atomic_read(&inode->i_count) != 1)
 		return -EBUSY;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	file->private_data = ctx;
 	if (!i->i_openers++)
 		ctx->mfc = inode->i_mapping;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return nonseekable_open(inode, file);
 }
 
@@ -1296,10 +1296,10 @@ spufs_mfc_release(struct inode *inode, struct file *file)
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	spin_lock(&ctx->mapping_lock);
+	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
 		ctx->mfc = NULL;
-	spin_unlock(&ctx->mapping_lock);
+	mutex_unlock(&ctx->mapping_lock);
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 0a947fd..47617e8 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -55,7 +55,7 @@ struct spu_context {
 	struct address_space *signal2;	   /* 'signal2' area mappings. */
 	struct address_space *mss;	   /* 'mss' area mappings. */
 	struct address_space *psmap;	   /* 'psmap' area mappings. */
-	spinlock_t mapping_lock;
+	struct mutex mapping_lock;
 	u64 object_id;		   /* user space pointer for oprofile */
 
 	enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
-- 
1.5.0.rc4.g85b1

^ permalink raw reply related

* [PATCH 4/6] spufs: free mm if spufs_fill_dir() failed
From: Jeremy Kerr @ 2007-06-04 13:26 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, cbe-oss-dev

From: Sebastian Siewior <bigeasy@linux.vnet.ibm.com>

In case spufs_fill_dir() fails only put_spu_context()
gets called for cleanup and the acquired mm_struct never gets freed.

Signed-off-by: Sebastian Siewior <bigeasy@linux.vnet.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---

 arch/powerpc/platforms/cell/spufs/inode.c |    1 +
 1 file changed, 1 insertion(+)

Index: linux-2.6-spufs/arch/powerpc/platforms/cell/spufs/inode.c
===================================================================
--- linux-2.6-spufs.orig/arch/powerpc/platforms/cell/spufs/inode.c
+++ linux-2.6-spufs/arch/powerpc/platforms/cell/spufs/inode.c
@@ -274,6 +274,7 @@ spufs_mkdir(struct inode *dir, struct de
 	goto out;
 
 out_free_ctx:
+	spu_forget(ctx);
 	put_spu_context(ctx);
 out_iput:
 	iput(inode);

^ permalink raw reply

* [PATCH 3/6] spufs: Fix gang destroy leaks.
From: Jeremy Kerr @ 2007-06-04 13:26 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, cbe-oss-dev

Previously, closing a SPE gang that still has contexts would trigger
a WARN_ON, and leak the allocated gang.

This change fixes the problem by using the gang's reference counts to
destroy the gang instead. The gangs will persist until their last
reference (be it context or open file handle) is gone.

Also, avoid using statements with side-effects in a WARN_ON().

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

---

 arch/powerpc/platforms/cell/spufs/inode.c |   40 +++---------------------------
 1 file changed, 5 insertions(+), 35 deletions(-)

Index: linux-2.6-spufs/arch/powerpc/platforms/cell/spufs/inode.c
===================================================================
--- linux-2.6-spufs.orig/arch/powerpc/platforms/cell/spufs/inode.c
+++ linux-2.6-spufs/arch/powerpc/platforms/cell/spufs/inode.c
@@ -349,37 +349,6 @@ out:
 	return ret;
 }
 
-static int spufs_rmgang(struct inode *root, struct dentry *dir)
-{
-	/* FIXME: this fails if the dir is not empty,
-	          which causes a leak of gangs. */
-	return simple_rmdir(root, dir);
-}
-
-static int spufs_gang_close(struct inode *inode, struct file *file)
-{
-	struct inode *parent;
-	struct dentry *dir;
-	int ret;
-
-	dir = file->f_path.dentry;
-	parent = dir->d_parent->d_inode;
-
-	ret = spufs_rmgang(parent, dir);
-	WARN_ON(ret);
-
-	return dcache_dir_close(inode, file);
-}
-
-const struct file_operations spufs_gang_fops = {
-	.open		= dcache_dir_open,
-	.release	= spufs_gang_close,
-	.llseek		= dcache_dir_lseek,
-	.read		= generic_read_dir,
-	.readdir	= dcache_readdir,
-	.fsync		= simple_sync_file,
-};
-
 static int
 spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
 {
@@ -407,7 +376,6 @@ spufs_mkgang(struct inode *dir, struct d
 	inode->i_fop = &simple_dir_operations;
 
 	d_instantiate(dentry, inode);
-	dget(dentry);
 	dir->i_nlink++;
 	dentry->d_inode->i_nlink++;
 	return ret;
@@ -437,7 +405,7 @@ static int spufs_gang_open(struct dentry
 		goto out;
 	}
 
-	filp->f_op = &spufs_gang_fops;
+	filp->f_op = &simple_dir_operations;
 	fd_install(ret, filp);
 out:
 	return ret;
@@ -458,8 +426,10 @@ static int spufs_create_gang(struct inod
 	 * in error path of *_open().
 	 */
 	ret = spufs_gang_open(dget(dentry), mntget(mnt));
-	if (ret < 0)
-		WARN_ON(spufs_rmgang(inode, dentry));
+	if (ret < 0) {
+		int err = simple_rmdir(inode, dentry);
+		WARN_ON(err);
+	}
 
 out:
 	mutex_unlock(&inode->i_mutex);

^ permalink raw reply

* [PATCH 2/6] spufs: hook up spufs_release_mem
From: Jeremy Kerr @ 2007-06-04 13:26 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, cbe-oss-dev

From: Christoph Hellwig <hch@lst.de>

Currently spufs_mem_release and the mem file doesn't have any release
method hooked up leading to leaks everytime is used.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 45614c7..89a5011 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -217,6 +217,7 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr,
 
 static const struct file_operations spufs_mem_fops = {
 	.open	 		= spufs_mem_open,
+	.release 		= spufs_mem_release,
 	.read   		= spufs_mem_read,
 	.write   		= spufs_mem_write,
 	.llseek  		= generic_file_llseek,
-- 
1.5.0.rc4.g85b1

^ permalink raw reply related

* [PATCH 1/6] spufs: refuse loading the module when not running on cell
From: Jeremy Kerr @ 2007-06-04 13:26 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, cbe-oss-dev

From: Arnd Bergmann <arnd.bergmann@de.ibm.com>

As noticed by David Woodhouse, it's currently possible to mount
spufs on any machine, which means that it actually will get
mounted by fedora.
This refuses to load the module on platforms that have no
support for SPUs.

Cc: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---

 arch/powerpc/platforms/cell/spufs/inode.c |    4 ++++
 1 file changed, 4 insertions(+)

Index: linux-2.6-spufs/arch/powerpc/platforms/cell/spufs/inode.c
===================================================================
--- linux-2.6-spufs.orig/arch/powerpc/platforms/cell/spufs/inode.c
+++ linux-2.6-spufs/arch/powerpc/platforms/cell/spufs/inode.c
@@ -600,6 +600,10 @@ spufs_create_root(struct super_block *sb
 	struct inode *inode;
 	int ret;
 
+	ret = -ENODEV;
+	if (!spu_management_ops)
+		goto out;
+
 	ret = -ENOMEM;
 	inode = spufs_new_inode(sb, S_IFDIR | 0775);
 	if (!inode)

^ permalink raw reply

* [PATCH 6/6] spufs,scheduler: fix wakeup races
From: Jeremy Kerr @ 2007-06-04 13:26 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, cbe-oss-dev

From: Christoph Hellwig <hch@lst.de>

Fix the race between checking for contexts on the runqueue and actually
waking them in spu_deactive and spu_yield.

The guts of spu_reschedule are split into a new helper called
grab_runnable_context which shows if there is a runnable thread below
a specified priority and if yes removes if from the runqueue and uses
it.  This function is used by the new __spu_deactivate hepler shared
by preemption and spu_yield to grab a new context before deactivating
a specified priority and if yes removes if from the runqueue and uses
it.  This function is used by the new __spu_deactivate hepler shared
by preemption and spu_yield to grab a new context before deactivating
the old one.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index b6ecb30..68fcdc4 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -93,43 +93,6 @@ void spu_stop_tick(struct spu_context *ctx)
 	}
 }
 
-void spu_sched_tick(struct work_struct *work)
-{
-	struct spu_context *ctx =
-		container_of(work, struct spu_context, sched_work.work);
-	struct spu *spu;
-	int preempted = 0;
-
-	/*
-	 * If this context is being stopped avoid rescheduling from the
-	 * scheduler tick because we would block on the state_mutex.
-	 * The caller will yield the spu later on anyway.
-	 */
-	if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
-		return;
-
-	mutex_lock(&ctx->state_mutex);
-	spu = ctx->spu;
-	if (spu) {
-		int best = sched_find_first_bit(spu_prio->bitmap);
-		if (best <= ctx->prio) {
-			spu_deactivate(ctx);
-			preempted = 1;
-		}
-	}
-	mutex_unlock(&ctx->state_mutex);
-
-	if (preempted) {
-		/*
-		 * We need to break out of the wait loop in spu_run manually
-		 * to ensure this context gets put on the runqueue again
-		 * ASAP.
-		 */
-		wake_up(&ctx->stop_wq);
-	} else
-		spu_start_tick(ctx);
-}
-
 /**
  * spu_add_to_active_list - add spu to active list
  * @spu:	spu to add to the active list
@@ -273,34 +236,6 @@ static void spu_prio_wait(struct spu_context *ctx)
 	remove_wait_queue(&ctx->stop_wq, &wait);
 }
 
-/**
- * spu_reschedule - try to find a runnable context for a spu
- * @spu:       spu available
- *
- * This function is called whenever a spu becomes idle.  It looks for the
- * most suitable runnable spu context and schedules it for execution.
- */
-static void spu_reschedule(struct spu *spu)
-{
-	int best;
-
-	spu_free(spu);
-
-	spin_lock(&spu_prio->runq_lock);
-	best = sched_find_first_bit(spu_prio->bitmap);
-	if (best < MAX_PRIO) {
-		struct list_head *rq = &spu_prio->runq[best];
-		struct spu_context *ctx;
-
-		BUG_ON(list_empty(rq));
-
-		ctx = list_entry(rq->next, struct spu_context, rq);
-		__spu_del_from_rq(ctx);
-		wake_up(&ctx->stop_wq);
-	}
-	spin_unlock(&spu_prio->runq_lock);
-}
-
 static struct spu *spu_get_idle(struct spu_context *ctx)
 {
 	struct spu *spu = NULL;
@@ -429,6 +364,51 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
 }
 
 /**
+ * grab_runnable_context - try to find a runnable context
+ *
+ * Remove the highest priority context on the runqueue and return it
+ * to the caller.  Returns %NULL if no runnable context was found.
+ */
+static struct spu_context *grab_runnable_context(int prio)
+{
+	struct spu_context *ctx = NULL;
+	int best;
+
+	spin_lock(&spu_prio->runq_lock);
+	best = sched_find_first_bit(spu_prio->bitmap);
+	if (best < prio) {
+		struct list_head *rq = &spu_prio->runq[best];
+
+		BUG_ON(list_empty(rq));
+
+		ctx = list_entry(rq->next, struct spu_context, rq);
+		__spu_del_from_rq(ctx);
+	}
+	spin_unlock(&spu_prio->runq_lock);
+
+	return ctx;
+}
+
+static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
+{
+	struct spu *spu = ctx->spu;
+	struct spu_context *new = NULL;
+
+	if (spu) {
+		new = grab_runnable_context(max_prio);
+		if (new || force) {
+			spu_unbind_context(spu, ctx);
+			spu_free(spu);
+			if (new)
+				wake_up(&new->stop_wq);
+		}
+
+	}
+
+	return new != NULL;
+}
+
+/**
  * spu_deactivate - unbind a context from it's physical spu
  * @ctx:	spu context to unbind
  *
@@ -437,12 +417,7 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
  */
 void spu_deactivate(struct spu_context *ctx)
 {
-	struct spu *spu = ctx->spu;
-
-	if (spu) {
-		spu_unbind_context(spu, ctx);
-		spu_reschedule(spu);
-	}
+	__spu_deactivate(ctx, 1, MAX_PRIO);
 }
 
 /**
@@ -455,18 +430,38 @@ void spu_deactivate(struct spu_context *ctx)
  */
 void spu_yield(struct spu_context *ctx)
 {
-	struct spu *spu;
+	mutex_lock(&ctx->state_mutex);
+	__spu_deactivate(ctx, 0, MAX_PRIO);
+	mutex_unlock(&ctx->state_mutex);
+}
 
-	if (mutex_trylock(&ctx->state_mutex)) {
-		if ((spu = ctx->spu) != NULL) {
-			int best = sched_find_first_bit(spu_prio->bitmap);
-			if (best < MAX_PRIO) {
-				pr_debug("%s: yielding SPU %d NODE %d\n",
-					 __FUNCTION__, spu->number, spu->node);
-				spu_deactivate(ctx);
-			}
-		}
-		mutex_unlock(&ctx->state_mutex);
+void spu_sched_tick(struct work_struct *work)
+{
+	struct spu_context *ctx =
+		container_of(work, struct spu_context, sched_work.work);
+	int preempted;
+
+	/*
+	 * If this context is being stopped avoid rescheduling from the
+	 * scheduler tick because we would block on the state_mutex.
+	 * The caller will yield the spu later on anyway.
+	 */
+	if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
+		return;
+
+	mutex_lock(&ctx->state_mutex);
+	preempted = __spu_deactivate(ctx, 0, ctx->prio + 1);
+	mutex_unlock(&ctx->state_mutex);
+
+	if (preempted) {
+		/*
+		 * We need to break out of the wait loop in spu_run manually
+		 * to ensure this context gets put on the runqueue again
+		 * ASAP.
+		 */
+		wake_up(&ctx->stop_wq);
+	} else {
+		spu_start_tick(ctx);
 	}
 }
 
-- 
1.5.0.rc4.g85b1

^ permalink raw reply related

* [PATCH 0/6] spufs fixes for 2.6.22
From: Jeremy Kerr @ 2007-06-04 13:26 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, cbe-oss-dev

Paul,

This series contains bugfixes for spufs - please consider these for
inclusion in 2.6.22.

Cheers,


Jeremy

^ permalink raw reply

* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Sergei Shtylyov @ 2007-06-04 13:16 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linux-mtd, Milton Miller, linuxppc-dev
In-Reply-To: <03427692d8865878b0eb2a91e7f6969e@kernel.crashing.org>

Hello.

Segher Boessenkool wrote:

>> Regarding physical address ranges for the flash mapping, I suppose the
>> best is to define a property for flash chips for it.

> There is, namely "reg".  How to best describe flash chips
> interleaved on the bus is still an open problem.  And things
> like combining two sequential in address space flash chips
> into a virtual one, or describing flash "partitions" doesn't
> belong in the device tree at all; it is a policy thing, not
> a hardware thing.

    Gah, it's becoming worse and worse...
    While I would agree with that argument, not having flash partition table 
in the device tree makes things even more ugly -- as we *already* can't use 
platform device to pass that info, we'll have to either force the user to 
supply that via the kernel option, or add more kludgery to Linux/MTD. :-/

> Segher

WBR, Sergei

^ permalink raw reply

* Re: [PATCH 4/21] spufs: Add a "capabilities" file to spu contexts
From: Jeremy Kerr @ 2007-06-04 13:06 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, Christoph Hellwig, cbe-oss-dev
In-Reply-To: <20070604051543.7028DDDEB9@ozlabs.org>

Ben,

> This adds a "capabilities" file to spu contexts consisting of a
> list of linefeed separated capability names. The current exposed
> capabilities are "sched" (the context is scheduleable) and
> "step" (the context supports single stepping).

Looks good.

Acked-by: Jeremy Kerr <jk@ozlabs.org>


Jeremy

^ permalink raw reply

* Re: [PATCH 3/21] spufs: Add support for SPU single stepping
From: Jeremy Kerr @ 2007-06-04 13:06 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, Christoph Hellwig, cbe-oss-dev
In-Reply-To: <20070604051542.43B6CDDE27@ozlabs.org>

> This patch adds support for SPU single stepping. The single
> step bit is set in the SPU when the current process is
> being single-stepped via ptrace. The spu then stops and
> returns with a specific flag set and the syscall exit code
> will generate the SIGTRAP.

Acked-by: Jeremy Kerr <jk@ozlabs.org>

Cheers,


Jeremy

^ permalink raw reply

* [RFC/PATCH 4/4] Add support for MSI on Axon-based Cell systems
From: Michael Ellerman @ 2007-06-04 13:00 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <f0cd638495b96585dec513f41335154e60675813.1180961962.git.michael@ellerman.id.au>

This patch adds support for the setup and decoding of MSIs
on Axon-based Cell systems.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

This still needs a bit of cleanup, but sending now for an early review.

 arch/powerpc/platforms/cell/Makefile   |    2 +
 arch/powerpc/platforms/cell/axon_msi.c |  412 ++++++++++++++++++++++++++++++++
 2 files changed, 414 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 869af89..6615d40 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -23,3 +23,5 @@ obj-$(CONFIG_SPU_BASE)			+= spu_callbacks.o spu_base.o \
 					   $(spu-priv1-y) \
 					   $(spu-manage-y) \
 					   spufs/
+
+obj-$(CONFIG_PCI_MSI)			+= axon_msi.o
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
new file mode 100644
index 0000000..2709853
--- /dev/null
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <linux/reboot.h>
+
+#include <asm/dcr.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+
+
+/*
+ * MSIC Control Register
+ */
+#define MSIC_CTRL_REG_ADDR	0x6F
+
+/* Flags */
+#define MSIC_ENABLE		0x0001	/* Bit 31 */
+#define MSIC_FIFO_FULL_ENABLE	0x0002	/* Bit 30 */
+#define MSIC_IRQ_ENABLE		0x0008	/* Bit 28 */
+#define MSIC_FULL_STOP_ENABLE	0x0010	/* Bit 27 */
+
+/* Size configuration constants */
+#define MSIC_SIZE_MASK		0x0180	/* Bits 22:23 */
+#define MSIC_SIZE_SHIFT		(7)
+#define	MSIC_SIZE_32K		0x0
+#define	MSIC_SIZE_64K		0x1
+#define	MSIC_SIZE_128K		0x2
+#define	MSIC_SIZE_256K		0x3
+
+/* The size we're actually using */
+#define MSIC_FIFO_SIZE		MSIC_SIZE_32K
+
+/* Different representations of the fifo size */
+#define MSIC_FIFO_SHIFT		(MSIC_FIFO_SIZE + 0xF)
+#define MSIC_FIFO_BYTES		(1 << MSIC_FIFO_SHIFT)
+#define MSIC_FIFO_MASK		(MSIC_FIFO_BYTES - 1)
+#define MSIC_FIFO_ORDER		max(MSIC_FIFO_SHIFT - PAGE_SHIFT, 0)
+
+/*
+ * MSIC Base Address registers (FIFO location)
+ */
+#define MSIC_BASE_ADDR_HI_REG	0x72
+#define MSIC_BASE_ADDR_LO_REG	0x73
+
+#define MSIC_READ_OFFSET_REG	0x74
+#define MSIC_WRITE_OFFSET_REG	0x75
+
+#define MSIC_DCR_BASE		MSIC_CTRL_REG_ADDR
+#define MSIC_DCR_SIZE		(MSIC_WRITE_OFFSET_REG - MSIC_CTRL_REG_ADDR)
+
+
+struct axon_msic {
+	struct device_node *dn;
+	struct irq_host *irq_host;
+	void *fifo;
+	dcr_host_t dcr_host;
+	struct list_head list;
+	u32 read_offset;
+};
+
+
+static LIST_HEAD(axon_msic_list);
+
+static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	struct axon_msic *msic = get_irq_data(irq);
+	u32 write_offset, msi;
+	unsigned int cirq;
+
+	write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
+	pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
+
+	/* write_offset doesn't wrap properly, so we have to mask it */
+	write_offset &= MSIC_FIFO_MASK;
+
+	while (msic->read_offset != write_offset) {
+		msi  = le32_to_cpup((__le32*)(msic->fifo + msic->read_offset));
+		msi &= 0xFFFF;
+
+		pr_debug("axon_msi: woff %x roff %x @ %p msi %x msi@0 %x\n",
+			write_offset, msic->read_offset,
+			msic->fifo + msic->read_offset, msi, *(u32*)msic->fifo);
+
+		msic->read_offset += 0x10;
+		msic->read_offset &= MSIC_FIFO_MASK;
+
+		cirq = irq_linear_revmap(msic->irq_host, msi);
+		if (cirq != NO_IRQ)
+			generic_handle_irq(cirq);
+		else
+			pr_debug("axon_msi: mapped to NO_IRQ!\n");
+	}
+
+	dcr_write(msic->dcr_host, MSIC_READ_OFFSET_REG, msic->read_offset);
+
+	desc->chip->eoi(irq);
+}
+
+static struct axon_msic *find_msi_translator(struct pci_dev *dev)
+{
+	struct irq_host *irq_host;
+	struct device_node *np, *tmp;
+	const phandle *ph;
+
+	np = pci_device_to_OF_node(dev);
+	if (!np) {
+		dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n");
+		return NULL;
+	}
+
+	for (; np; tmp = of_get_parent(np), of_node_put(np), np = tmp) {
+		ph = of_get_property(np, "msi-translator", NULL);
+		if (ph)
+			break;
+	}
+
+	if (!ph) {
+		dev_dbg(&dev->dev, "axon_msi: no msi-translator found\n");
+		goto out_error;
+	}
+
+	tmp = np;
+	np = of_find_node_by_phandle(*ph);
+	if (!np) {
+		dev_dbg(&dev->dev, "axon_msi: invalid msi-translator found\n");
+		goto out_error;
+	}
+
+	irq_host = irq_find_host(np);
+	if (!irq_host) {
+		dev_dbg(&dev->dev, "axon_msi: no irq_host found\n");
+		goto out_error;
+	}
+
+	return irq_host->host_data;
+
+out_error:
+	of_node_put(np);
+	of_node_put(tmp);
+
+	return NULL;
+}
+
+static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+	if (!find_msi_translator(dev))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
+{
+	struct device_node *np, *tmp;
+	int pos, len;
+	u16 flags;
+	const u32 *prop;
+
+	np = pci_device_to_OF_node(dev);
+	if (!np) {
+		dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n");
+		return -ENODEV;
+	}
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (!pos || pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &flags)) {
+		dev_err(&dev->dev, "axon_msi: error reading config space!\n");
+		return -EIO;
+	}
+
+	for (; np; tmp = of_get_parent(np), of_node_put(np), np = tmp) {
+		if (flags & PCI_MSI_FLAGS_64BIT) {
+			prop = of_get_property(np, "msi-address-64", &len);
+			if (prop)
+				break;
+		}
+
+		prop = of_get_property(np, "msi-address-32", &len);
+		if (prop)
+			break;
+	}
+	of_node_put(np);
+
+	if (!prop) {
+		dev_dbg(&dev->dev, "axon_msi: no msi-address-(32|64) found\n");
+		return -ENOENT;
+	}
+
+	switch (len) {
+	case 8:
+		msg->address_hi = prop[0];
+		msg->address_lo = prop[1];
+		break;
+	case 4:
+		msg->address_hi = 0;
+		msg->address_lo = prop[0];
+		break;
+	default:
+		dev_dbg(&dev->dev, "axon_msi: malformed msi-address-(32|64)\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	unsigned int virq, rc;
+	struct msi_desc *entry;
+	struct msi_msg msg;
+	struct axon_msic *msic;
+
+	msic = find_msi_translator(dev);
+	if (!msic)
+		return -ENODEV;
+
+	rc = setup_msi_msg_address(dev, &msg);
+	if (rc)
+		return rc;
+
+	/* We rely on being able to stash a virq in a u16 */
+	BUILD_BUG_ON(NR_IRQS > 65536);
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		virq = irq_create_direct_mapping(msic->irq_host);
+		if (virq == NO_IRQ) {
+			pr_debug("axon_msi: virq allocation failed!\n");
+			return -1;
+		}
+		pr_debug("axon_msi: allocated virq 0x%x for %s\n",
+			 virq, pci_name(dev));
+
+		set_irq_msi(virq, entry);
+		msg.data = virq;
+		write_msi_msg(virq, &msg);
+	}
+
+	return 0;
+}
+
+static void axon_msi_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+
+	pr_debug("axon_msi: tearing down irqs for %s\n", pci_name(dev));
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		if (entry->irq == NO_IRQ)
+			continue;
+
+		set_irq_msi(entry->irq, NULL);
+		irq_dispose_mapping(entry->irq);
+	}
+}
+
+static struct irq_chip msic_irq_chip = {
+	.mask		= mask_msi_irq,
+	.unmask		= unmask_msi_irq,
+	.shutdown	= unmask_msi_irq,
+	.typename	= "AXON-MSI",
+};
+
+static int msic_host_map(struct irq_host *h, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	set_irq_chip_and_handler(virq, &msic_irq_chip, handle_simple_irq);
+	return 0;
+}
+
+static int msic_host_match(struct irq_host *host, struct device_node *node)
+{
+	struct axon_msic *msic = host->host_data;
+	return msic->dn == node;
+}
+
+static struct irq_host_ops msic_host_ops = {
+	.match	= msic_host_match,
+	.map	= msic_host_map,
+};
+
+static int axon_msi_notify_reboot(struct notifier_block *nb,
+				  unsigned long code, void *data)
+{
+	struct axon_msic *msic;
+	u32 tmp;
+
+	list_for_each_entry(msic, &axon_msic_list, list) {
+		tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG_ADDR);
+		tmp &= ~MSIC_ENABLE;
+		dcr_write(msic->dcr_host, MSIC_CTRL_REG_ADDR, tmp);
+		pr_debug("axon_msi: disabling %s\n", msic->dn->full_name);
+	}
+
+	return 0;
+}
+
+static struct notifier_block axon_msi_reboot_notifier = {
+	.notifier_call = axon_msi_notify_reboot
+};
+
+static int axon_msi_setup_one(struct device_node *node)
+{
+	struct page *page;
+	struct axon_msic *msic;
+	unsigned int virq;
+
+	pr_debug("axon_msi: setting up dn %s\n", node->full_name);
+
+	msic = kzalloc(sizeof(struct axon_msic), GFP_KERNEL);
+	if (!msic) {
+		printk(KERN_ERR "axon_msi: couldn't allocate msic\n");
+		goto out_put;
+	}
+
+	msic->dn = node;
+
+	msic->dcr_host = dcr_map(node, MSIC_DCR_BASE, MSIC_DCR_SIZE);
+	if (!DCR_MAP_OK(msic->dcr_host)) {
+		printk(KERN_ERR "axon_msi: dcr_map failed\n");
+		goto out_free_msic;
+	}
+
+	page = alloc_pages_node(of_node_to_nid(node),
+				GFP_KERNEL, MSIC_FIFO_ORDER);
+	if (!page) {
+		printk(KERN_ERR "axon_msi: couldn't allocate fifo\n");
+		goto out_free_msic;
+	}
+
+	msic->fifo = page_address(page);
+
+	msic->irq_host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, NR_IRQS,
+					&msic_host_ops, 0);
+	if (!msic->irq_host) {
+		printk(KERN_ERR "axon_msi: couldn't allocate host\n");
+		goto out_free_fifo;
+	}
+
+	msic->irq_host->host_data = msic;
+
+	virq = irq_of_parse_and_map(node, 0);
+	if (virq == NO_IRQ) {
+		printk(KERN_ERR "axon_msi: irq parse/map failed!\n");
+		goto out_free_host;
+	}
+
+	set_irq_data(virq, msic);
+	set_irq_chained_handler(virq, axon_msi_cascade);
+	pr_debug("axon_msi: irq 0x%x setup for axon_msi!\n", virq);
+
+	/* Enable the MSIC hardware */
+	dcr_write(msic->dcr_host, MSIC_BASE_ADDR_HI_REG,
+				  (u64)msic->fifo >> 32);
+	dcr_write(msic->dcr_host, MSIC_BASE_ADDR_LO_REG,
+				  (u64)msic->fifo & 0xFFFFFFFF);
+	dcr_write(msic->dcr_host, MSIC_CTRL_REG_ADDR,
+				  MSIC_IRQ_ENABLE | MSIC_ENABLE |
+				  (MSIC_FIFO_SIZE << MSIC_SIZE_SHIFT));
+
+	list_add(&msic->list, &axon_msic_list);
+
+	return 0;
+
+out_free_host:
+	kfree(msic->irq_host);
+out_free_fifo:
+	__free_pages(virt_to_page(msic->fifo), MSIC_FIFO_ORDER);
+out_free_msic:
+	kfree(msic);
+out_put:
+	of_node_put(node);
+
+	return -1;
+}
+
+static int axon_msi_init(void)
+{
+	struct device_node *node;
+	int found = 0;
+
+	pr_debug("axon_msi: initialising ...\n");
+
+	for_each_compatible_node(node, NULL, "ibm,axon-msic") {
+		if (axon_msi_setup_one(of_node_get(node)) == 0)
+			found++;
+	}
+	of_node_put(node);
+
+	if (found) {
+		ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
+		ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
+		ppc_md.msi_check_device = axon_msi_check_device;
+
+		register_reboot_notifier(&axon_msi_reboot_notifier);
+
+		pr_debug("axon_msi: registered callbacks!\n");
+	}
+
+	return 0;
+}
+arch_initcall(axon_msi_init);
-- 
1.5.1.3.g7a33b-dirty

^ permalink raw reply related

* [PATCH 3/4] Add for_each_compatible_node()
From: Michael Ellerman @ 2007-06-04 13:00 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <f0cd638495b96585dec513f41335154e60675813.1180961962.git.michael@ellerman.id.au>

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 include/asm-powerpc/prom.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 6845af9..1122a92 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -124,6 +124,9 @@ extern struct device_node *of_find_node_by_type(struct device_node *from,
 	     dn = of_find_node_by_type(dn, type))
 extern struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compat);
+#define for_each_compatible_node(dn, type, compatible) \
+	for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
+	     dn = of_find_compatible_node(dn, type, compatible))
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
-- 
1.5.1.3.g7a33b-dirty

^ permalink raw reply related

* [PATCH 2/4] Add irq_create_direct_mapping()
From: Michael Ellerman @ 2007-06-04 13:00 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <f0cd638495b96585dec513f41335154e60675813.1180961962.git.michael@ellerman.id.au>

This patch adds irq_create_direct_mapping(). This routine is
an alternative to irq_create_mapping(), for irq controllers that
can use linux virq numbers directly as hardware numbers.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/irq.c |   24 ++++++++++++++++++++++++
 include/asm-powerpc/irq.h |    9 +++++++++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 9bafc88..fdb3b00 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -611,6 +611,30 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 	return 0;
 }
 
+unsigned int irq_create_direct_mapping(struct irq_host *host)
+{
+	unsigned int virq;
+
+	if (host == NULL)
+		host = irq_default_host;
+
+	BUG_ON(host == NULL);
+	WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
+
+	virq = irq_alloc_virt(host, 1, 0);
+	if (virq == NO_IRQ) {
+		pr_debug("irq: create_direct virq allocation failed\n");
+		return NO_IRQ;
+	}
+
+	pr_debug("irq: create_direct obtained virq %d\n", virq);
+
+	if (irq_setup_virq(host, virq, virq))
+		return NO_IRQ;
+
+	return virq;
+}
+
 unsigned int irq_create_mapping(struct irq_host *host,
 				irq_hw_number_t hwirq)
 {
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 4734cc1..8384e3f 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -226,6 +226,15 @@ extern void irq_dispose_mapping(unsigned int virq);
 extern unsigned int irq_find_mapping(struct irq_host *host,
 				     irq_hw_number_t hwirq);
 
+/**
+ * irq_create_direct_mapping - Allocate a virq for direct mapping
+ * @host: host to allocate the virq for or NULL for default host
+ *
+ * This routine is used for irq controllers which can choose the hardware
+ * interrupt numbers they generate. In such a case it's simplest to use
+ * the linux virq as the hardware interrupt number.
+ */
+extern unsigned int irq_create_direct_mapping(struct irq_host *host);
 
 /**
  * irq_radix_revmap - Find a linux virq from a hw irq number.
-- 
1.5.1.3.g7a33b-dirty

^ permalink raw reply related

* [PATCH 1/4] Split virq setup logic out into irq_setup_virq()
From: Michael Ellerman @ 2007-06-04 12:59 UTC (permalink / raw)
  To: linuxppc-dev

A future patch will need the logic at the end of irq_create_mapping()
which setups a virq and installs it in the irq_map. So split it out
into a new function irq_setup_virq().

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/irq.c |   32 +++++++++++++++++++++-----------
 1 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 42c8ed6..9bafc88 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -591,6 +591,25 @@ static void irq_radix_rdunlock(unsigned long flags)
 	local_irq_restore(flags);
 }
 
+static int irq_setup_virq(struct irq_host *host, unsigned int virq,
+			    irq_hw_number_t hwirq)
+{
+	/* Clear IRQ_NOREQUEST flag */
+	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
+
+	/* map it */
+	smp_wmb();
+	irq_map[virq].hwirq = hwirq;
+	smp_mb();
+
+	if (host->ops->map(host, virq, hwirq)) {
+		pr_debug("irq: -> mapping failed, freeing\n");
+		irq_free_virt(virq, 1);
+		return -1;
+	}
+
+	return 0;
+}
 
 unsigned int irq_create_mapping(struct irq_host *host,
 				irq_hw_number_t hwirq)
@@ -639,18 +658,9 @@ unsigned int irq_create_mapping(struct irq_host *host,
 	}
 	pr_debug("irq: -> obtained virq %d\n", virq);
 
-	/* Clear IRQ_NOREQUEST flag */
-	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
-
-	/* map it */
-	smp_wmb();
-	irq_map[virq].hwirq = hwirq;
-	smp_mb();
-	if (host->ops->map(host, virq, hwirq)) {
-		pr_debug("irq: -> mapping failed, freeing\n");
-		irq_free_virt(virq, 1);
+	if (irq_setup_virq(host, virq, hwirq))
 		return NO_IRQ;
-	}
+
 	return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
-- 
1.5.1.3.g7a33b-dirty

^ permalink raw reply related

* Re: [PATCH 2/2] ehea: Receive SKB Aggregation
From: Christoph Raisch @ 2007-06-04 12:09 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Thomas Q Klein, ossthema, Jeff Garzik, Jan-Bernd Themann, netdev,
	linux-kernel, Stefan Roscher, linux-ppc, Marcus Eder, tklein
In-Reply-To: <20070531134118.GA30501@infradead.org>


Christoph Hellwig wrote on 31.05.2007 15:41:18:

> I'm still very unhappy with having all this in various drivers.  There's
> a lot of code that can be turned into generic library functions, and even
> more code that could be made generic with some amount of refactoring.

Yes, we'd also prefer to use a generic function, but we first would want to
get
some "real world" experience how our driver behaves with LRO to be even
able to
define requirements for such a generic function. A lot of this is tied into
pathlengths,
caching, and why does that help compared to a different TCP receive side
processing?
In a perfect world we shouldn't see a diffference if this is enabled or
not,
but measurements indicate something completely different at 10gbit.

Gruss / Regards
Christoph Raisch

^ permalink raw reply

* Re: [PATCH 2/2] ehea: Receive SKB Aggregation
From: Christoph Raisch @ 2007-06-04 12:09 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Thomas Q Klein, ossthema, Jeff Garzik, Jan-Bernd Themann, netdev,
	linux-kernel, Stefan Roscher, linux-ppc, Marcus Eder, tklein
In-Reply-To: <20070531093703.373995b2@freepuppy>



Stephen Hemminger  wrote on 31.05.2007 18:37:03:

>
> >
> >
> > +static int try_get_ip_tcp_hdr(struct ehea_cqe *cqe, struct sk_buff
*skb,
> > +               struct iphdr **iph, struct tcphdr **tcph)
> > +{
> > +   int ip_len;
> > +
> > +   /* non tcp/udp packets */
> > +   if (!cqe->header_length)
> > +      return -1;
> > +
> > +   /* non tcp packet */
> > +   *iph = (struct iphdr *)(skb->data);
>
> Why the indirection, copying of headers..
This interacts with the header split function in the hardware.
>
> > +   if ((*iph)->protocol != IPPROTO_TCP)
> > +      return -1;
> > +
> > +   ip_len = (u8)((*iph)->ihl);
> > +   ip_len <<= 2;
> > +   *tcph = (struct tcphdr *)(((u64)*iph) + ip_len);
> > +
> > +   return 0;
> > +}
> > +
> >
>
> This code seems to be duplicating a lot  (but not all) of the TCP/IP
> input path validation checks. This is a security problem if nothing
else...
>
We should only do aggregation in the driver if this really is a TCP header,
otherwise things will get worse.
You're right, we should at least check that tcph is within the received
frame.

> Also, how do you prevent DoS attacks from hostile TCP senders that send
> huge number of back to back frames?

Actually a huge number of back to back frames is what we would want to
receive
at 10 gbit ;-)
How is it possible to figure out if this is what you want or just DoS?
It doesn't change anything compared to a non LRO driver, we process a
certain
maximum amount of frames before waiting for the next interrupt,
the packet filters/DoS should still see all traffic (which is above the
driver).
Any suggestions how to handle this better/different?

>
> --
> Stephen Hemminger

Gruss / Regards
Christoph Raisch

^ permalink raw reply

* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Sergei Shtylyov @ 2007-06-04 12:41 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-mtd, Milton Miller
In-Reply-To: <1180905120.31677.22.camel@localhost.localdomain>

Hello.

Benjamin Herrenschmidt wrote:

>>    No, it doesn't -- since that info is almost *absolutely* useless
>>(the only 
>>exception is "cfi") in the context of Linux MTD subsys.
>>    Please, try to understand that knowing that chip is CFI compatible in 
>>itself doesn't yet guarantee that you can access the chip -- it all depends on 
>>its mapping to the real physical address range, therefore this group IMO 
>>cannot even constitute a valid "compatible" property.

> You make no sense to me. It's like saying that knowing that a 8250 chip
> on ISA cannot be accessed if you don't know it's IO ports so it
> shouldn't say "8250" in compatible property ?!?!?!?

    No, it's a completely different case.  Base address and even flash size 
are not the only things that matter.  There's bus width and interleave factors 
that influence the access (and possibly, byte-swapping too, although this is 
unlikely to happen in PPC world).

> Also, whatever shortcomings of the linux MTD drivers are totally
> irrelevant to what is correct to have in a device-tree. While we do
> tailor our device-tree specification around linux needs in most cases,
> there are cases like this one where common sense should be enough to
> understand that it's not because the linux MTD subsystem, as of today,
> cannot be told what programming interface to use, that we shouldn't
> provide that information in the tree.

    We did provide it, in the form of probing hints ("probe-type" prop).

> Regarding physical address ranges for the flash mapping, I suppose the
> best is to define a property for flash chips for it. 

    Flash chips in themselves have little to do with how they are mapped to 
the physical address space (considers the interleave factor), so that doesn't 
seem a practical idea.

WBR, Sergei

^ permalink raw reply

* Re: [PATCH] powerpc: Create "rom" (MTD) device prpmc2800
From: Sergei Shtylyov @ 2007-06-04 12:34 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: ppcdev, linux-mtd, Milton Miller
In-Reply-To: <1180904670.31677.18.camel@localhost.localdomain>

Benjamin Herrenschmidt wrote:
>>>>the CFI/JEDEC interface then can be deduced by probing

>>>Most of the time, sure.  Not always.

>>    That's the way the cookie crumbles in Linux MTD for now. It's
>>*always* 
>>detecting this by probing -- you only can say what [not] to probe. 

> So you are saying that because the current linux MTD stuff can only
> probe (which doesn't always work), we should not put the proper chip
> interface type in the device-tree ?

    No. But if/when we put it, it'll only be able to influence interface 
probing, but not "force" the interface.

> Your argument makes no sense to me.

    As I said, that's the way the cookie crumbles.

> Put the proper interface informations in the device-tree, maybe some OS
> smarter than linux will make good use on it and maybe linux will be
> fixed at one point too (not by you, of course, you gave us that line
> often enough about not being paid to do the right thing).

    The money was not the only factor, you know, I was under the pressure of 
schedules, and had a lot more things to do.

> Ben.

WBR, Sergei

^ permalink raw reply

* 83xx GPIO/EXT int in arch/powerpc/
From: Marc Leeman @ 2007-06-04  9:56 UTC (permalink / raw)
  To: linuxppc-dev

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


I am moving my boards from arch/ppc/ to arch/powerpc/ and am trying to
use the MPC83xx_IRQ_EXT? pins.

The device (hardcoded to use 23 as with the arch/ppc/ config, EXT7)
does not signal the ints to the CPU.

The only reference I find to this usage in arch/powerpc/ is in
arch/powerpc/platforms/83xx/mpc834x_itx.h, which is most likely
something left over while moving from arch/ppc/

Probably, I need to enable them in the dts tree (?) but since it's a PCI
device that uses a GPIO pin for signalling interrupts, I'm trying to
find out where and how to configure this.

Is there some example for e.g. an 83xx board how to configure one of
those external interrupt pins?

-- 
  greetz, marc
It's like Disney on acid! Ten years of really great sex all at the
same moment.
	Crichton - Rhapsody in Blue
chiana 2.6.18-4-ixp4xx #1 Tue Mar 27 18:01:56 BST 2007 GNU/Linux

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

^ permalink raw reply

* Re: [PATCH] Fix interrupt distribution in ppc970
From: Mohan Kumar M @ 2007-06-04 10:54 UTC (permalink / raw)
  To: Milton Miller; +Cc: ppcdev, kexec, Paul Mackerras
In-Reply-To: <ca045e7e6fde9345b3461214777d8102@bga.com>

Milton,

How about this patch?

=============================================================
In some of the PPC970 based systems, interrupt would be distributed to
offline cpus also even when booted with "maxcpus=1". So check whether
cpu online map and cpu present map are equal or not. If they are equal
default_distrib_server is used as interrupt server otherwise boot cpu
(default_server) used as interrupt server. 

In addition to this, if an interrupt is assigned to a specific cpu (ie
smp affinity) and if that cpu is not online, the earlier code used to
return the default_distrib_server as interrupt server. This patch
introduces an additional paramter to the get_irq function ie
strict_check, based on this parameter, if the cpu is not online either
default_distrib_server or -1 is returned.

Cc: Milton Miller <miltonm@bga.com>,
    Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Mohan Kumar M <mohan@in.ibm.com>
---
 arch/powerpc/platforms/pseries/xics.c |   54 ++++++++++++++++++----------------
 1 file changed, 29 insertions(+), 25 deletions(-)

Index: linux-2.6.21.1/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- linux-2.6.21.1.orig/arch/powerpc/platforms/pseries/xics.c
+++ linux-2.6.21.1/arch/powerpc/platforms/pseries/xics.c
@@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_
 
 
 #ifdef CONFIG_SMP
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
-	unsigned int server;
+	int server;
 	/* For the moment only implement delivery to all cpus or one cpu */
 	cpumask_t cpumask = irq_desc[virq].affinity;
 	cpumask_t tmp = CPU_MASK_NONE;
@@ -166,22 +166,24 @@ static int get_irq_server(unsigned int v
 	if (!distribute_irqs)
 		return default_server;
 
-	if (cpus_equal(cpumask, CPU_MASK_ALL)) {
-		server = default_distrib_server;
-	} else {
+	if (!cpus_equal(cpumask, CPU_MASK_ALL)) {
 		cpus_and(tmp, cpu_online_map, cpumask);
 
-		if (cpus_empty(tmp))
-			server = default_distrib_server;
-		else
-			server = get_hard_smp_processor_id(first_cpu(tmp));
-	}
+		server = first_cpu(tmp);
 
-	return server;
+		if (server < NR_CPUS)
+			return get_hard_smp_processor_id(server);
+		else if (strict_check)
+				return -1;
+	}
 
+	if (cpus_equal(cpu_online_map, cpu_present_map))
+		return default_distrib_server;
+	else
+		return default_server;
 }
 #else
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
 	return default_server;
 }
@@ -192,7 +194,7 @@ static void xics_unmask_irq(unsigned int
 {
 	unsigned int irq;
 	int call_status;
-	unsigned int server;
+	int server;
 
 	pr_debug("xics: unmask virq %d\n", virq);
 
@@ -201,7 +203,7 @@ static void xics_unmask_irq(unsigned int
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
 
-	server = get_irq_server(virq);
+	server = get_irq_server(virq, 0);
 
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
 				DEFAULT_PRIORITY);
@@ -398,8 +400,7 @@ static void xics_set_affinity(unsigned i
 	unsigned int irq;
 	int status;
 	int xics_status[2];
-	unsigned long newmask;
-	cpumask_t tmp = CPU_MASK_NONE;
+	int irq_server;
 
 	irq = (unsigned int)irq_map[virq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
@@ -413,18 +414,21 @@ static void xics_set_affinity(unsigned i
 		return;
 	}
 
-	/* For the moment only implement delivery to all cpus or one cpu */
-	if (cpus_equal(cpumask, CPU_MASK_ALL)) {
-		newmask = default_distrib_server;
-	} else {
-		cpus_and(tmp, cpu_online_map, cpumask);
-		if (cpus_empty(tmp))
-			return;
-		newmask = get_hard_smp_processor_id(first_cpu(tmp));
+	/*
+	 * For the moment only implement delivery to all cpus or one cpu.
+	 * Get current irq_server for the given irq
+	 */
+	irq_server = get_irq_server(irq, 1);
+	if (irq_server == -1) {
+		char cpulist[128];
+		cpulist_scnprintf(cpulist, sizeof(cpulist), cpumask);
+		printk(KERN_WARNING "xics_set_affinity: No online cpus in "
+				"the mask %s for irq %d\n", cpulist, virq);
+		return;
 	}
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
-				irq, newmask, xics_status[1]);
+				irq, irq_server, xics_status[1]);
 
 	if (status) {
 		printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "

^ 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