* Re: [PATCH] eeh: Fixing a bug when pci structure is null
From: Mike Mason @ 2010-02-24 22:13 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Linas Vepstas, Breno Leitao
In-Reply-To: <1266616485.23523.1026.camel@pasglop>
On 2/19/2010 1:54 PM, Benjamin Herrenschmidt wrote:
> On Fri, 2010-02-19 at 14:43 -0200, Breno Leitao wrote:
>> Hi Ben,
>>
>> I'd like to ask about this patch ? Should I re-submit ?
>>
>> Thanks,
>>
>> Breno Leitao wrote:
>>> During a EEH recover, the pci_dev structure can be null, mainly if an
>>> eeh event is detected during cpi config operation. In this case, the
>>> pci_dev will not be known (and will be null) the kernel will crash
>>> with the following message:
>
> It should be in -next, can you dbl check ?
I just confirmed the patch is in the -next tree.
Mike
>
> Cheers,
> Ben.
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: PCI on 834x
From: Gary Thomas @ 2010-02-24 22:14 UTC (permalink / raw)
To: avorontsov; +Cc: Scott Wood, linuxppc-dev
In-Reply-To: <20100224205159.GA6555@oksana.dev.rtsoft.ru>
On 02/24/2010 01:51 PM, Anton Vorontsov wrote:
> On Wed, Feb 24, 2010 at 02:26:20PM -0600, Scott Wood wrote:
>> Gary Thomas wrote:
>>> Yes, I'm using the exact same kernel with these two different PCI
>>> setups (done by the boot loader).
>>>
>>> Restricting the memory via mem=128M has no effect - the PCI layout
>>> is the same.
>>>
>>> I think the outbound window size is required because of how the Linux PCI
>>> remaps the space (note in my dumps that it put the MMIO of the
>>> boards starting
>>> at 0xD0000000 when the inbound window is 0x10000000)
>>
>> I see where the amount of RAM is mattering -- Linux is assigning
>> outbound I/O space to the PCI controller itself (device 00:00.0) and
>> the amount that it asks for seems to differ based on memory size.
>> Linux ought to skip that device when assigning resources. Some
>> platforms do this (search for pci_exclude_device), but it seems to
>> be missing on 83xx.
>
> Actually, 83xx had these exclude_device hooks, but they were removed:
>
> commit d8f1324a5063c833862328ceafabc53ac3cc4f71
> Author: Kumar Gala<galak@kernel.crashing.org>
> Date: Wed Sep 12 22:14:10 2007 -0500
>
> [POWERPC] 83xx: Removed PCI exclude of PHB
>
> Now that the generic code doesn't assign resources for Freescale
> PHBs we dont have to explicitly exclude it.
>
> Signed-off-by: Kumar Gala<galak@kernel.crashing.org>
>
>
> May be the generic code started to assign the resources again?
>
That cracked it; I re-enabled the exclusion of the bridge and now
it's all working fine.
Thanks for the help
Note: I'm working with a fairly old kernel, so these results would
have to be reworked against the latest.
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* [PATCH v2] powerpc: Add hibernation support for FSL BookE processors
From: Anton Vorontsov @ 2010-02-24 21:38 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
This is started as swsusp_32.S modifications, but the amount of #ifdefs
made the whole file horribly unreadable, so let's put the support into
its own separate file.
The code should be relatively easy to modify to support 44x BookEs as
well, but since I don't have any 44x to test, let's confine the code to
FSL BookE. (The only FSL-specific parts are 'flush_dcache_L1' and TLB
invalidation code).
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Sorry for the delayed response...
On Tue, Jan 12, 2010 at 01:34:08PM +1100, Benjamin Herrenschmidt wrote:
[...]
> Here's a quick review. Looks good but two things:
>
> - Please make it swsusp_booke.c, 44x support is trivial and I don't
> want to rename the file :-)
Done.
> - Is there really an SDR1 register on FSL BookE ? It's supposed to be
> the pointer to the hash table on server ...
Thanks, fixed.
> - You probably should save/restore the TCR and ack pending crap DEC or
> FIT interrupts in the TSR right before you kick the decrementer
Done.
> - Nowadays, we still assume that the "loader" kernel is exactly the
> same as the "loaded" kernel on resume ?
I'm pretty sure today we do rely on this, yes. This is not some
generic code limitation though, it's just hard to test the case
when loader != loaded. In most cases it will work fine since the
loader kernel wouldn't differ a lot from the loaded kernel, so
it'll setup the low level stuff the same way.
We may try to link the loader kernel to a different address
(relocate it as in kdump case), and hope that it'll trigger
all sort of problems so that we could fix them.
Though, the better test case would be to resume the hibernated
kernel directly from the bootloader.
Thanks,
arch/powerpc/kernel/Makefile | 8 +-
arch/powerpc/kernel/swsusp_booke.S | 200 ++++++++++++++++++++++++++++++++++++
2 files changed, 206 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/kernel/swsusp_booke.S
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c002b04..33d9dda 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_E500) += idle_e500.o
obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU) += tau_6xx.o
-obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \
- swsusp_$(CONFIG_WORD_SIZE).o
+obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
+ifeq ($(CONFIG_FSL_BOOKE),y)
+obj-$(CONFIG_HIBERNATION) += swsusp_booke.o
+else
+obj-$(CONFIG_HIBERNATION) += swsusp_$(CONFIG_WORD_SIZE).o
+endif
obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o
obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_44x) += cpu_setup_44x.o
diff --git a/arch/powerpc/kernel/swsusp_booke.S b/arch/powerpc/kernel/swsusp_booke.S
new file mode 100644
index 0000000..dbffad2
--- /dev/null
+++ b/arch/powerpc/kernel/swsusp_booke.S
@@ -0,0 +1,200 @@
+/*
+ * Based on swsusp_32.S, modified for FSL BookE by
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Copyright (c) 2009-2010 MontaVista Software, LLC.
+ */
+
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/mmu.h>
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_SP 0
+#define SL_PC 4
+#define SL_MSR 8
+#define SL_TCR 0xc
+#define SL_SPRG0 0x10
+#define SL_SPRG1 0x14
+#define SL_SPRG2 0x18
+#define SL_SPRG3 0x1c
+#define SL_SPRG4 0x20
+#define SL_SPRG5 0x24
+#define SL_SPRG6 0x28
+#define SL_SPRG7 0x2c
+#define SL_TBU 0x30
+#define SL_TBL 0x34
+#define SL_R2 0x38
+#define SL_CR 0x3c
+#define SL_LR 0x40
+#define SL_R12 0x44 /* r12 to r31 */
+#define SL_SIZE (SL_R12 + 80)
+
+ .section .data
+ .align 5
+
+_GLOBAL(swsusp_save_area)
+ .space SL_SIZE
+
+
+ .section .text
+ .align 5
+
+_GLOBAL(swsusp_arch_suspend)
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+
+ mflr r0
+ stw r0,SL_LR(r11)
+ mfcr r0
+ stw r0,SL_CR(r11)
+ stw r1,SL_SP(r11)
+ stw r2,SL_R2(r11)
+ stmw r12,SL_R12(r11)
+
+ /* Save MSR & TCR */
+ mfmsr r4
+ stw r4,SL_MSR(r11)
+ mfspr r4,SPRN_TCR
+ stw r4,SL_TCR(r11)
+
+ /* Get a stable timebase and save it */
+1: mftbu r4
+ stw r4,SL_TBU(r11)
+ mftb r5
+ stw r5,SL_TBL(r11)
+ mftbu r3
+ cmpw r3,r4
+ bne 1b
+
+ /* Save SPRGs */
+ mfsprg r4,0
+ stw r4,SL_SPRG0(r11)
+ mfsprg r4,1
+ stw r4,SL_SPRG1(r11)
+ mfsprg r4,2
+ stw r4,SL_SPRG2(r11)
+ mfsprg r4,3
+ stw r4,SL_SPRG3(r11)
+ mfsprg r4,4
+ stw r4,SL_SPRG4(r11)
+ mfsprg r4,5
+ stw r4,SL_SPRG5(r11)
+ mfsprg r4,6
+ stw r4,SL_SPRG6(r11)
+ mfsprg r4,7
+ stw r4,SL_SPRG7(r11)
+
+ /* Call the low level suspend stuff (we should probably have made
+ * a stackframe...
+ */
+ bl swsusp_save
+
+ /* Restore LR from the save area */
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+ lwz r0,SL_LR(r11)
+ mtlr r0
+
+ blr
+
+_GLOBAL(swsusp_arch_resume)
+ sync
+
+ /* Load ptr the list of pages to copy in r3 */
+ lis r11,(restore_pblist)@h
+ ori r11,r11,restore_pblist@l
+ lwz r3,0(r11)
+
+ /* Copy the pages. This is a very basic implementation, to
+ * be replaced by something more cache efficient */
+1:
+ li r0,256
+ mtctr r0
+ lwz r5,pbe_address(r3) /* source */
+ lwz r6,pbe_orig_address(r3) /* destination */
+2:
+ lwz r8,0(r5)
+ lwz r9,4(r5)
+ lwz r10,8(r5)
+ lwz r11,12(r5)
+ addi r5,r5,16
+ stw r8,0(r6)
+ stw r9,4(r6)
+ stw r10,8(r6)
+ stw r11,12(r6)
+ addi r6,r6,16
+ bdnz 2b
+ lwz r3,pbe_next(r3)
+ cmpwi 0,r3,0
+ bne 1b
+
+ bl flush_dcache_L1
+ bl flush_instruction_cache
+
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+
+ lwz r4,SL_SPRG0(r11)
+ mtsprg 0,r4
+ lwz r4,SL_SPRG1(r11)
+ mtsprg 1,r4
+ lwz r4,SL_SPRG2(r11)
+ mtsprg 2,r4
+ lwz r4,SL_SPRG3(r11)
+ mtsprg 3,r4
+ lwz r4,SL_SPRG4(r11)
+ mtsprg 4,r4
+ lwz r4,SL_SPRG5(r11)
+ mtsprg 5,r4
+ lwz r4,SL_SPRG6(r11)
+ mtsprg 6,r4
+ lwz r4,SL_SPRG7(r11)
+ mtsprg 7,r4
+
+ /* Invalidate TLB0 & TLB1 */
+ li r6,0x04
+ tlbivax 0,r6
+ TLBSYNC
+ li r6,0x0c
+ tlbivax 0,r6
+ TLBSYNC
+
+ /* restore the MSR */
+ lwz r3,SL_MSR(r11)
+
+ /* Restore TB */
+ li r3,0
+ mttbl r3
+ lwz r3,SL_TBU(r11)
+ lwz r4,SL_TBL(r11)
+ mttbu r3
+ mttbl r4
+
+ /* Restore TCR and clear any pending bits in TSR. */
+ lwz r4,SL_TCR(r11)
+ mtspr SPRN_TCR,r4
+ lis r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
+ mtspr SPRN_TSR,r4
+
+ /* Kick decrementer */
+ li r0,1
+ mtdec r0
+
+ /* Restore the callee-saved registers and return */
+ lwz r0,SL_CR(r11)
+ mtcr r0
+ lwz r2,SL_R2(r11)
+ lmw r12,SL_R12(r11)
+ lwz r1,SL_SP(r11)
+ lwz r0,SL_LR(r11)
+ mtlr r0
+
+ li r3,0
+ blr
--
1.7.0
^ permalink raw reply related
* Re: PCI on 834x
From: Anton Vorontsov @ 2010-02-24 20:51 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Gary Thomas
In-Reply-To: <4B858B6C.4020809@freescale.com>
On Wed, Feb 24, 2010 at 02:26:20PM -0600, Scott Wood wrote:
> Gary Thomas wrote:
> >Yes, I'm using the exact same kernel with these two different PCI
> >setups (done by the boot loader).
> >
> >Restricting the memory via mem=128M has no effect - the PCI layout
> >is the same.
> >
> >I think the outbound window size is required because of how the Linux PCI
> >remaps the space (note in my dumps that it put the MMIO of the
> >boards starting
> >at 0xD0000000 when the inbound window is 0x10000000)
>
> I see where the amount of RAM is mattering -- Linux is assigning
> outbound I/O space to the PCI controller itself (device 00:00.0) and
> the amount that it asks for seems to differ based on memory size.
> Linux ought to skip that device when assigning resources. Some
> platforms do this (search for pci_exclude_device), but it seems to
> be missing on 83xx.
Actually, 83xx had these exclude_device hooks, but they were removed:
commit d8f1324a5063c833862328ceafabc53ac3cc4f71
Author: Kumar Gala <galak@kernel.crashing.org>
Date: Wed Sep 12 22:14:10 2007 -0500
[POWERPC] 83xx: Removed PCI exclude of PHB
Now that the generic code doesn't assign resources for Freescale
PHBs we dont have to explicitly exclude it.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
May be the generic code started to assign the resources again?
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: PCI on 834x
From: Scott Wood @ 2010-02-24 20:26 UTC (permalink / raw)
To: Gary Thomas; +Cc: linuxppc-dev
In-Reply-To: <4B858243.8010908@mlbassoc.com>
Gary Thomas wrote:
> Yes, I'm using the exact same kernel with these two different PCI
> setups (done by the boot loader).
>
> Restricting the memory via mem=128M has no effect - the PCI layout is
> the same.
>
> I think the outbound window size is required because of how the Linux PCI
> remaps the space (note in my dumps that it put the MMIO of the boards
> starting
> at 0xD0000000 when the inbound window is 0x10000000)
I see where the amount of RAM is mattering -- Linux is assigning
outbound I/O space to the PCI controller itself (device 00:00.0) and the
amount that it asks for seems to differ based on memory size. Linux
ought to skip that device when assigning resources. Some platforms do
this (search for pci_exclude_device), but it seems to be missing on 83xx.
>> Are there any errors indicated in the device, the PCI controller, the
>> arbiter, etc?
>
> None that are obvious to me.
>
> To be clear, here are my observations:
>
> * total memory 128MB (or less), inbound window 128MB, outbound window 128MB
> ==> device is happy
> * total memory 256MB, inbound window 128MB, outbound window 128MB
> ==> device hangs, unable to access RAM (Linux handed it something
> higher than 128MB)
Linux gets its idea of how much space there is to allocate from the
ranges property of the pci node in the device tree -- this should be
made to match what u-boot configures in PIWARn.
> * total memory 256MB, inbound window 256MB, outbound window 128MB
> ==> segmentation violation when accessing device MMIO space
> * total memory 256MB, inbound window 256MB, outbound window 256MB
> ==> access to MMIO space fails (Linux can't find device). In this
> case, the SATA_SIL reports
> ata1: SATA link down (SStatus FFFFFFFF SControl FFFFFFFF)
> ata2: SATA link down (SStatus FFFFFFFF SControl FFFFFFFF)
> which implies that the driver get's junk when accessing the device
> MMIO space
Are there any other relevant messages earlier in boot, perhaps from the
PCI code failing to assign a resource?
-Scott
^ permalink raw reply
* Re: [PATCH 3/7] RapidIO: Add Port-Write handling for EM
From: Micha Nelissen @ 2010-02-24 20:17 UTC (permalink / raw)
To: Alexandre Bounine
Cc: linuxppc-dev, linux-kernel, thomas.moll.ext, thomas.moll
In-Reply-To: <20100224152401.GC13661@kaneng01.tundra.com>
Alexandre Bounine wrote:
> /**
> + * rio_em_set_ops- Sets Error Managment operations for a particular vendor switch
> + * @rdev: RIO device
> + *
> + * Searches the RIO EM ops table for known switch types. If the vid
> + * and did match a switch table entry, then set the em_init() and
> + * em_handle() ops to the table entry values.
Shouldn't any RIO device be able to support error management, not just
switches?
> +/**
> + * rio_pw_enable - Enables/disables port-write handling by a master port
> + * @port: Master port associated with port-write handling
> + * @enable: 1=enable, 0=disable
> + */
> +static void rio_pw_enable(struct rio_mport *port, int enable)
> +{
> + if (port->ops->pwenable)
> + port->ops->pwenable(port, enable);
> +}
> +
Maybe this can be done by switch->init function?
> +/**
> + * rio_inb_pwrite_handler - process inbound port-write message
> + * @pw_msg: pointer to inbound port-write message
> + *
> + * Processes an inbound port-write message. Returns 0 if the request
> + * has been satisfied.
> + */
> +int rio_inb_pwrite_handler(u32 *pw_msg)
> +{
Perhaps map this pw_msg to a struct? Or read it into named variables?
> + /* Clear Port Errors */
> + rio_mport_write_config_32(mport, destid, hopcount,
> + rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
> + err_status & 0x07120204);
Hardcoded value!
> +
> + if (rdev->rswitch->port_ok & (1 << portnum)) {
> + if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) {
> + rdev->rswitch->port_ok &= ~(1 << portnum);
> + rio_mport_read_config_32(mport, destid, hopcount,
> + rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
> + ®val);
> + rio_mport_write_config_32(mport, destid, hopcount,
> + rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
> + regval | RIO_PORT_N_CTL_LOCKOUT);
You have a function for this?
> + rio_mport_write_config_32(mport, destid, hopcount,
> + rdev->phys_efptr +
> + RIO_PORT_N_ACK_STS_CSR(portnum),
> + RIO_PORT_N_ACK_CLEAR);
This doesn't work for the 568; but the 568 has no special handling?
> + /* Clear Port-Write Pending bit */
> + rio_mport_write_config_32(mport, destid, hopcount,
> + rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
> + RIO_PORT_N_ERR_STS_PW_PEND);
> +DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_em_init, tsi57x_em_handler);
> +DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_em_init, tsi57x_em_handler);
> +DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_em_init, tsi57x_em_handler);
> +DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_em_init, tsi57x_em_handler);
Why not declare these along with the other ops?
Micha
^ permalink raw reply
* Re: [PATCH 1/7] RapidIO: Add IDT CPS/TSI switches
From: Micha Nelissen @ 2010-02-24 20:02 UTC (permalink / raw)
To: Alexandre Bounine
Cc: linux-kernel, thomas.moll, linuxppc-dev, alexandreb,
thomas.moll.ext
In-Reply-To: <20100224151447.GA13661@kaneng01.tundra.com>
Alexandre Bounine wrote:
> @@ -369,6 +380,10 @@ static struct rio_dev __devinit *rio_set
> rdev->rswitch->switchid);
> rio_route_set_ops(rdev);
>
> + if (do_enum && rdev->rswitch->clr_table)
> + rdev->rswitch->clr_table(port, destid, hopcount,
> + RIO_GLOBAL_TABLE);
> +
> list_add_tail(&rswitch->node, &rio_switches);
>
> } else
Why clear the tables here, why not in rio_enum_peer?
> +DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
> +DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
> +DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
> +DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
Can the 568 and 578 driver be shared? Have a 5xx driver?
Micha
^ permalink raw reply
* Re: PCI on 834x
From: Gary Thomas @ 2010-02-24 19:47 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <4B857EA1.6030605@freescale.com>
On 02/24/2010 12:31 PM, Scott Wood wrote:
> Gary Thomas wrote:
>> On 02/24/2010 11:48 AM, Scott Wood wrote:
>>> Gary Thomas wrote:
>>>> Does anyone have experience setting up the PCI controller on
>>>> the MPC8349? I have it running fine when my system has 128MB
>>>> or less of main memory, but when I have 256MB or more, it all
>>>> falls apart :-(
>>>>
>>>> Any indication of the pertinent settings would be appreciated.
>>>
>>> Check the inbound PCI translation registers, especially PIWARn.
>>
>> Yes, I set it to 256MB (the size of RAM).
>> I also set PCI_AR0 to a 512MB window (when it's set to 256, I
>> get address [segmentation violation] errors when accessing my
>> devices that end up at the high end of the logical address space)
>> Finally, I set POCMR0 to a 512MB window (corresponding to PCI_AR0)
>
> I don't see what the outbound window size has to do with RAM size... are there any other differences between the 128MiB and 256MiB setups? Same exact software? What happens if you
> take the 256MiB setup and restrict the kernel to using the lower 128MiB ("mem=128M" on the kernel bootargs), with no other changes? What happens if you use a 512MiB outbound window
> on the 128MiB setup?
Yes, I'm using the exact same kernel with these two different PCI
setups (done by the boot loader).
Restricting the memory via mem=128M has no effect - the PCI layout is the same.
I think the outbound window size is required because of how the Linux PCI
remaps the space (note in my dumps that it put the MMIO of the boards starting
at 0xD0000000 when the inbound window is 0x10000000)
> Is this behavior consistent across multiple boards (i.e. could there be a hardware problem)?
I've had this same problem on many platforms before (834x and 8248 as well). In the
past, I didn't have the time to spend fixing it, so I just worked around it by limiting
the system to 128MB in the boot loader + PCI setup)
> Are there any errors indicated in the device, the PCI controller, the arbiter, etc?
None that are obvious to me.
To be clear, here are my observations:
* total memory 128MB (or less), inbound window 128MB, outbound window 128MB
==> device is happy
* total memory 256MB, inbound window 128MB, outbound window 128MB
==> device hangs, unable to access RAM (Linux handed it something higher than 128MB)
* total memory 256MB, inbound window 256MB, outbound window 128MB
==> segmentation violation when accessing device MMIO space
* total memory 256MB, inbound window 256MB, outbound window 256MB
==> access to MMIO space fails (Linux can't find device). In this case, the SATA_SIL reports
ata1: SATA link down (SStatus FFFFFFFF SControl FFFFFFFF)
ata2: SATA link down (SStatus FFFFFFFF SControl FFFFFFFF)
which implies that the driver get's junk when accessing the device MMIO space
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* Re: [PATCH 2/7] RapidIO: Add switch locking during discovery
From: Micha Nelissen @ 2010-02-24 19:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20100224152050.GB13661@kaneng01.tundra.com>
Alexandre Bounine wrote:
> + /* Attempt to acquire device lock */
> + rio_mport_write_config_32(port, destid,
> + hopcount,
> + RIO_HOST_DID_LOCK_CSR,
> + port->host_deviceid);
> + rio_mport_read_config_32(port, destid, hopcount,
> + RIO_HOST_DID_LOCK_CSR, &result);
> + while (result != port->host_deviceid) {
It's better to abstract the locking of a device into a new function,
rio_lock_device / rio_unlock_device.
Then you can use those in rio_get_route_entry and rio_add_route_entry.
> @@ -1027,6 +1090,13 @@ int __devinit rio_disc_mport(struct rio_
> +
> + /* Read DestID assigned by enumerator */
> + rio_local_read_config_32(mport, RIO_DID_CSR,
> + &mport->host_deviceid);
> + mport->host_deviceid = RIO_GET_DID(mport->sys_size,
> + mport->host_deviceid);
> +
This fixes something else, should be a separate patch.
Regards, Micha
^ permalink raw reply
* Re: PCI on 834x
From: Scott Wood @ 2010-02-24 19:31 UTC (permalink / raw)
To: Gary Thomas; +Cc: linuxppc-dev
In-Reply-To: <4B857AA8.9000208@mlbassoc.com>
Gary Thomas wrote:
> On 02/24/2010 11:48 AM, Scott Wood wrote:
>> Gary Thomas wrote:
>>> Does anyone have experience setting up the PCI controller on
>>> the MPC8349? I have it running fine when my system has 128MB
>>> or less of main memory, but when I have 256MB or more, it all
>>> falls apart :-(
>>>
>>> Any indication of the pertinent settings would be appreciated.
>>
>> Check the inbound PCI translation registers, especially PIWARn.
>
> Yes, I set it to 256MB (the size of RAM).
> I also set PCI_AR0 to a 512MB window (when it's set to 256, I
> get address [segmentation violation] errors when accessing my
> devices that end up at the high end of the logical address space)
> Finally, I set POCMR0 to a 512MB window (corresponding to PCI_AR0)
I don't see what the outbound window size has to do with RAM size... are
there any other differences between the 128MiB and 256MiB setups? Same
exact software? What happens if you take the 256MiB setup and restrict
the kernel to using the lower 128MiB ("mem=128M" on the kernel
bootargs), with no other changes? What happens if you use a 512MiB
outbound window on the 128MiB setup?
Is this behavior consistent across multiple boards (i.e. could there be
a hardware problem)?
Are there any errors indicated in the device, the PCI controller, the
arbiter, etc?
-Scott
^ permalink raw reply
* Re: PCI on 834x
From: Gary Thomas @ 2010-02-24 19:14 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <4B85746F.3020200@freescale.com>
On 02/24/2010 11:48 AM, Scott Wood wrote:
> Gary Thomas wrote:
>> Does anyone have experience setting up the PCI controller on
>> the MPC8349? I have it running fine when my system has 128MB
>> or less of main memory, but when I have 256MB or more, it all
>> falls apart :-(
>>
>> Any indication of the pertinent settings would be appreciated.
>
> Check the inbound PCI translation registers, especially PIWARn.
Yes, I set it to 256MB (the size of RAM).
I also set PCI_AR0 to a 512MB window (when it's set to 256, I
get address [segmentation violation] errors when accessing my
devices that end up at the high end of the logical address space)
Finally, I set POCMR0 to a 512MB window (corresponding to PCI_AR0)
In this configuration, my device doesn't seem to be able to
access RAM. If PIWAR1 is too small, the device just hangs.
=============================== 128MB setup =========================
PIWAR1 = 0xA0055000 | (27-1)
POCMR0 = 0x800F0000
PCIAR0 = 0x80000000 | (28-1)
00:00.0 Power PC: Unknown device 1957:0082 (rev 30)
Flags: bus master, 66MHz, fast devsel, latency 0
Memory at cc000000 (32-bit, non-prefetchable) [size=1M]
Memory at c0000000 (64-bit, prefetchable) [size=128M]
Memory at <unassigned> (64-bit, non-prefetchable)
Capabilities: [48] #06 [0000]
00:0b.0 Mass storage controller: Silicon Image, Inc. SiI 3512 [SATALink/SATARaid] Serial ATA Controller (rev 01)
Subsystem: Silicon Image, Inc. SiI 3512 SATALink Controller
Flags: bus master, 66MHz, medium devsel, latency 0, IRQ 22
I/O ports at 1000 [size=8]
I/O ports at 1008 [size=4]
I/O ports at 1010 [size=8]
I/O ports at 1018 [size=4]
I/O ports at 1020 [size=16]
Memory at cc180000 (32-bit, non-prefetchable) [size=512]
[virtual] Expansion ROM at cc100000 [disabled] [size=512K]
Capabilities: [60] Power Management version 2
00:0c.0 Display controller: Fujitsu Limited. Unknown device 2019 (rev 01)
Flags: bus master, medium devsel, latency 0, IRQ 19
Memory at c8000000 (32-bit, non-prefetchable) [size=64M]
=====================================================================
=============================== 256MB setup =========================
PIWAR1 = 0xA0055000 | (28-1)
POCMR0 = 0x800E0000
PCIAR0 = 0x80000000 | (29-1)
00:00.0 Power PC: Unknown device 1957:0082 (rev 30)
Flags: bus master, 66MHz, fast devsel, latency 0
Memory at d4000000 (32-bit, non-prefetchable) [size=1M]
Memory at c0000000 (64-bit, prefetchable) [size=256M]
Memory at <unassigned> (64-bit, non-prefetchable)
Capabilities: [48] #06 [0000]
00:0b.0 Mass storage controller: Silicon Image, Inc. SiI 3512 [SATALink/SATARaid] Serial ATA Controller (rev 01)
Subsystem: Silicon Image, Inc. SiI 3512 SATALink Controller
Flags: bus master, 66MHz, medium devsel, latency 0, IRQ 22
I/O ports at 1000 [size=8]
I/O ports at 1008 [size=4]
I/O ports at 1010 [size=8]
I/O ports at 1018 [size=4]
I/O ports at 1020 [size=16]
Memory at d4180000 (32-bit, non-prefetchable) [size=512]
[virtual] Expansion ROM at d4100000 [disabled] [size=512K]
Capabilities: [60] Power Management version 2
00:0c.0 Display controller: Fujitsu Limited. Unknown device 2019 (rev 01)
Flags: bus master, medium devsel, latency 0, IRQ 19
[virtual] Memory at d0000000 (32-bit, non-prefetchable) [size=64M]
=====================================================================
Any ideas what I might be missing?
Thanks
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* MPC8313 and IO mapping a localbus space.
From: Mike Williamson @ 2010-02-24 19:12 UTC (permalink / raw)
To: linuxppc-dev
Hi,
I'm working on implementing a linux 2.6.23 kernel for a machine based
on the MPC8313. It's
basically a clone of the Freescale ERDB dev kit module with the
addition of an FPGA on CS3 of the localbus.
(it also has NAND and a FLASH NOR part on the localbus as well).
All of the code is based off of the ltib BSP kit provided by
Freescale's 2008-12-22 release.
I am able to address the FPGA in u-boot using "md.w" as well as all
the other localbus devices.
However, when I load up linux, I can't seem to map in the FPGA and
read or write to it. I don't bus error,
I just get zeros.
The driver code is pretty basic (below), and I've verified that the
LBLAWARx and LBLAWBARx registers
match what was set in u-boot. I've also verified that the eLBC ORx
and BRx registers match.
The only thing that seems to be missing is that there aren't entries
in the BATs for anything
but the SDRAM. This is a bit confusing because I seem to be able to
read from NAND and NOR
mtd devices without any issues.
Is there more that I need to do beyond an ioremap() to map in the address space?
Thanks.
-Mike
#define HW_FPGA 0xfa000000
#define HW_FPGA_SIZE 32768
static int __init mapfpga_load(void)
{
u16 tmp;
int res = 0;
printk(KERN_ALERT "%s: loading\n", dev_name);
mapfpga_dev.fpgaimg_res = request_mem_region(HW_FPGA,
HW_FPGA_SIZE, dev_name);
if (mapfpga_dev.fpgaimg_res == NULL) {
printk(KERN_ALERT "%s: could not request memory region"
" 0x%08x\n", dev_name, HW_FPGA);
res = -EINVAL;
goto out;
}
mapfpga_dev.fpgaimg = ioremap_nocache(HW_FPGA, HW_FPGA_SIZE);
if (mapfpga_dev.fpgaimg == NULL) {
printk(KERN_ALERT "%s: could not map i/o region"
" 0x%08x\n", dev_name, HW_FPGA);
res = -EINVAL;
goto out;
}
/* this should generate a non-zero number, it's a version register */
tmp = ioread16(mapfpga_dev.fpgaimg); /* always zero... */
...
}
--
Michael Williamson
315-425-4045x230
www.criticallink.com
^ permalink raw reply
* Re: PCI on 834x
From: Scott Wood @ 2010-02-24 18:48 UTC (permalink / raw)
To: Gary Thomas; +Cc: linuxppc-dev
In-Reply-To: <4B854A93.7030405@mlbassoc.com>
Gary Thomas wrote:
> Does anyone have experience setting up the PCI controller on
> the MPC8349? I have it running fine when my system has 128MB
> or less of main memory, but when I have 256MB or more, it all
> falls apart :-(
>
> Any indication of the pertinent settings would be appreciated.
Check the inbound PCI translation registers, especially PIWARn.
-Scott
^ permalink raw reply
* PCI on 834x
From: Gary Thomas @ 2010-02-24 15:49 UTC (permalink / raw)
To: linuxppc-dev
Does anyone have experience setting up the PCI controller on
the MPC8349? I have it running fine when my system has 128MB
or less of main memory, but when I have 256MB or more, it all
falls apart :-(
Any indication of the pertinent settings would be appreciated.
Thanks
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* Re: [PATCH] powerpc: Set a smaller value for RECLAIM_DISTANCE to enable zone reclaim
From: Christoph Lameter @ 2010-02-24 15:43 UTC (permalink / raw)
To: Anton Blanchard; +Cc: Mel Gorman, linuxppc-dev
In-Reply-To: <20100223015551.GG31681@kryten>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1244 bytes --]
On Tue, 23 Feb 2010, Anton Blanchard wrote:
> zone_reclaim_mode.txt
> Now we set zone_reclaim_mode = 1. On each iteration we continue to improve,
> but even after 10 runs of stream we have > 10% remote node memory usage.
The intend of zone reclaim was never to allocate all memory from on node.
You should not expect all memory to come from the node even if zone
reclaim works.
> reclaim_4096_pages.txt
> Instead of reclaiming 32 pages at a time, we try for a much larger batch
> of 4096. The slope is much steeper but it still takes around 6 iterations
> to get almost all local node memory.
"almost all"? How much do you want?
> wait_on_busy_flag.txt
> Here we busy wait if the ZONE_RECLAIM_LOCKED flag is set. As you suggest
> we would need to check the GFP flags etc, but so far it looks the most
> promising. We only get a few percent of remote node memory on the first
> iteration and get all local node by the second.
This would significantly impact performance. Zone reclaim should reclaim
with minimal overhead. If zone reclaim is running on another processor
then the OS already takes measures against the shortage of node local
memory. The right thing to do is to take what is currently available which
may be off node memory.
[-- Attachment #2: Type: IMAGE/PNG, Size: 34767 bytes --]
[-- Attachment #3: Type: TEXT/X-DIFF, Size: 387 bytes --]
--- mm/vmscan.c~ 2010-02-21 23:47:14.000000000 -0600
+++ mm/vmscan.c 2010-02-22 03:22:01.000000000 -0600
@@ -2534,7 +2534,7 @@
.may_unmap = !!(zone_reclaim_mode & RECLAIM_SWAP),
.may_swap = 1,
.nr_to_reclaim = max_t(unsigned long, nr_pages,
- SWAP_CLUSTER_MAX),
+ 4096),
.gfp_mask = gfp_mask,
.swappiness = vm_swappiness,
.order = order,
[-- Attachment #4: Type: TEXT/X-DIFF, Size: 495 bytes --]
--- mm/vmscan.c~ 2010-02-21 23:47:14.000000000 -0600
+++ mm/vmscan.c 2010-02-21 23:47:31.000000000 -0600
@@ -2634,8 +2634,8 @@
if (node_state(node_id, N_CPU) && node_id != numa_node_id())
return ZONE_RECLAIM_NOSCAN;
- if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED))
- return ZONE_RECLAIM_NOSCAN;
+ while (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED))
+ cpu_relax();
ret = __zone_reclaim(zone, gfp_mask, order);
zone_clear_flag(zone, ZONE_RECLAIM_LOCKED);
^ permalink raw reply
* [PATCH 7/7] powerpc/85xx: Fix the RapidIO maintenance access functions
From: Alexandre Bounine @ 2010-02-24 15:37 UTC (permalink / raw)
To: mporter; +Cc: abounine, linuxppc-dev, linux-kernel, thomas.moll.ext,
thomas.moll
From: Thomas Moll <thomas.moll@sysgo.com>
Fix the maintenance access functions to farend RapidIO devices.
1. Fixed shift of the given offset, to open the maintenance window
2. Mask offset to limit access to the opened maintenance window
3. Added extended destid part to rowtear register, required for 16bit mode
For easier handling of the access routines, the access was limited to aligned
memory regions. This should be no problem because all registers are 32bit
wide.
Signed-off-by: Thomas Moll <thomas.moll@sysgo.com>
---
fsl_rio.c | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff -purN linux-base/arch/powerpc/sysdev/fsl_rio.c linux-new/arch/powerpc/sysdev/fsl_rio.c
--- linux-base/arch/powerpc/sysdev/fsl_rio.c 2010-02-24 08:37:05.000000000 +0100
+++ linux-new/arch/powerpc/sysdev/fsl_rio.c 2010-02-24 08:45:27.000000000 +0100
@@ -1,6 +1,10 @@
/*
* Freescale MPC85xx/MPC86xx RapidIO support
*
+ * Copyright 2009 Sysgo AG
+ * Thomas Moll <thomas.moll@sysgo.com>
+ * - fixed maintenance access routines, check for aligned access
+ *
* Copyright 2009 Integrated Device Technology, Inc.
* Alex Bounine <alexandre.bounine@idt.com>
* - Added Port-Write message handling
@@ -370,10 +374,17 @@ fsl_rio_config_read(struct rio_mport *mp
pr_debug
("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
index, destid, hopcount, offset, len);
+
+ /* 16MB maintenance window possible */
+ /* allow only aligned access to maintenance registers */
+ if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
+ return -EINVAL;
+
out_be32(&priv->maint_atmu_regs->rowtar,
- (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+ (destid << 22) | (hopcount << 12) | (offset >> 12));
+ out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
- data = (u8 *) priv->maint_win + offset;
+ data = (u8 *) priv->maint_win + (offset & 0x3FFFFF);
switch (len) {
case 1:
__fsl_read_rio_config(rval, data, err, "lbz");
@@ -381,9 +392,11 @@ fsl_rio_config_read(struct rio_mport *mp
case 2:
__fsl_read_rio_config(rval, data, err, "lhz");
break;
- default:
+ case 4:
__fsl_read_rio_config(rval, data, err, "lwz");
break;
+ default:
+ return -EINVAL;
}
if (err) {
@@ -418,10 +431,17 @@ fsl_rio_config_write(struct rio_mport *m
pr_debug
("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
index, destid, hopcount, offset, len, val);
+
+ /* 16MB maintenance windows possible */
+ /* allow only aligned access to maintenance registers */
+ if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
+ return -EINVAL;
+
out_be32(&priv->maint_atmu_regs->rowtar,
- (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+ (destid << 22) | (hopcount << 12) | (offset >> 12));
+ out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
- data = (u8 *) priv->maint_win + offset;
+ data = (u8 *) priv->maint_win + (offset & 0x3FFFFF);
switch (len) {
case 1:
out_8((u8 *) data, val);
@@ -429,9 +449,11 @@ fsl_rio_config_write(struct rio_mport *m
case 2:
out_be16((u16 *) data, val);
break;
- default:
+ case 4:
out_be32((u32 *) data, val);
break;
+ default:
+ return -EINVAL;
}
return 0;
---
Important Notice: This message is intended for the use of the individual to whom it is addressed and may contain information which is privileged, confidential and/or exempt from disclosure under applicable law. If the reader of this message is not the intended recipient, or is not the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender immediately by telephone or return e-mail and delete the original message from your systems. Thank you.
^ permalink raw reply
* [PATCH 1/7] RapidIO: Add IDT CPS/TSI switches
From: Alexandre Bounine @ 2010-02-24 15:14 UTC (permalink / raw)
To: mporter
Cc: alexandreb, linuxppc-dev, linux-kernel, thomas.moll.ext,
thomas.moll
From: Alexandre Bounine <alexandre.bounine@idt.com>
Extentions to RapidIO switch support:
1. modify switch route operation declarations to allow using single
switch-specific file for family of switches that share the same route
table operations.
2. add standard route table operations for switches that that support
route table manipulation registers as defined in the Rev.1.3 of RapidIO
specification.
3. add clear-route-table operation for switches
4. add CPSxx and TSIxxx families of RapidIO switches
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Tested-by: Thomas Moll <thomas.moll@sysgo.com>
---
drivers/rapidio/rio-scan.c | 17 +++++-
drivers/rapidio/rio.c | 104 +++++++++++++++++++++++++++++++++++++
drivers/rapidio/rio.h | 20 +++++--
drivers/rapidio/switches/Makefile | 2
drivers/rapidio/switches/idtcps.c | 84 ++++++++++++++++++++++++++++++
drivers/rapidio/switches/tsi500.c | 2
drivers/rapidio/switches/tsi568.c | 106 ++++++++++++++++++++++++++++++++++++++
drivers/rapidio/switches/tsi57x.c | 106 ++++++++++++++++++++++++++++++++++++++
include/linux/rio.h | 6 ++
include/linux/rio_ids.h | 14 +++++
include/linux/rio_regs.h | 14 ++++-
11 files changed, 464 insertions(+), 11 deletions(-)
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/rio-scan.c w33r7d/drivers/rapidio/rio-scan.c
--- w33r7c/drivers/rapidio/rio-scan.c 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/drivers/rapidio/rio-scan.c 2010-02-22 11:06:23.913470000 -0500
@@ -55,6 +55,7 @@ static int rio_mport_phys_table[] = {
static int rio_sport_phys_table[] = {
RIO_EFB_PAR_EP_FREE_ID,
RIO_EFB_SER_EP_FREE_ID,
+ RIO_EFB_SER_EP_FREC_ID,
-1,
};
@@ -246,10 +247,20 @@ static void rio_route_set_ops(struct rio
pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev));
rdev->rswitch->add_entry = cur->add_hook;
rdev->rswitch->get_entry = cur->get_hook;
+ rdev->rswitch->clr_table = cur->clr_hook;
+ break;
}
cur++;
}
+ if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
+ pr_debug("RIO: adding STD routing ops for %s\n",
+ rio_name(rdev));
+ rdev->rswitch->add_entry = rio_std_route_add_entry;
+ rdev->rswitch->get_entry = rio_std_route_get_entry;
+ rdev->rswitch->clr_table = rio_std_route_clr_table;
+ }
+
if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
printk(KERN_ERR "RIO: missing routing ops for %s\n",
rio_name(rdev));
@@ -349,7 +360,7 @@ static struct rio_dev __devinit *rio_set
if (rio_is_switch(rdev)) {
rio_mport_read_config_32(port, destid, hopcount,
RIO_SWP_INFO_CAR, &rdev->swpinfo);
- rswitch = kmalloc(sizeof(struct rio_switch), GFP_KERNEL);
+ rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL);
if (!rswitch)
goto cleanup;
rswitch->switchid = next_switchid;
@@ -369,6 +380,10 @@ static struct rio_dev __devinit *rio_set
rdev->rswitch->switchid);
rio_route_set_ops(rdev);
+ if (do_enum && rdev->rswitch->clr_table)
+ rdev->rswitch->clr_table(port, destid, hopcount,
+ RIO_GLOBAL_TABLE);
+
list_add_tail(&rswitch->node, &rio_switches);
} else
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/rio.c w33r7d/drivers/rapidio/rio.c
--- w33r7c/drivers/rapidio/rio.c 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/drivers/rapidio/rio.c 2010-02-22 11:06:23.937564000 -0500
@@ -451,6 +451,110 @@ struct rio_dev *rio_get_device(u16 vid,
return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
}
+/**
+ * rio_std_route_add_entry - Add switch route table entry using standard
+ * registers defined in RIO specification rev.1.3
+ * @mport: Master port to issue transaction
+ * @destid: Destination ID of the device
+ * @hopcount: Number of switch hops to the device
+ * @table: routing table ID (global or port-specific)
+ * @route_destid: destID entry in the RT
+ * @route_port: destination port for specified destID
+ */
+int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 route_port)
+{
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_DESTID_SEL_CSR,
+ (u32)route_destid);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_PORT_SEL_CSR,
+ (u32)route_port);
+ }
+ udelay(10);
+ return 0;
+}
+
+/**
+ * rio_std_route_get_entry - Read switch route table entry (port number)
+ * assosiated with specified destID using standard registers defined in RIO
+ * specification rev.1.3
+ * @mport: Master port to issue transaction
+ * @destid: Destination ID of the device
+ * @hopcount: Number of switch hops to the device
+ * @table: routing table ID (global or port-specific)
+ * @route_destid: destID entry in the RT
+ * @route_port: returned destination port for specified destID
+ */
+int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 *route_port)
+{
+ u32 result;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
+ rio_mport_read_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
+
+ *route_port = (u8)result;
+ }
+
+ return 0;
+}
+
+/**
+ * rio_std_route_clr_table - Clear swotch route table using standard registers
+ * defined in RIO specification rev.1.3.
+ * @mport: Master port to issue transaction
+ * @local: Indicate a local master port or remote device access
+ * @destid: Destination ID of the device
+ * @hopcount: Number of switch hops to the device
+ * @table: routing table ID (global or port-specific)
+ */
+int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table)
+{
+ u32 max_destid = 0xff;
+ u32 i, pef, id_inc = 1, ext_cfg = 0;
+ u32 port_sel = RIO_INVALID_ROUTE;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_read_config_32(mport, destid, hopcount,
+ RIO_PEF_CAR, &pef);
+
+ if (mport->sys_size) {
+ rio_mport_read_config_32(mport, destid, hopcount,
+ RIO_SWITCH_RT_LIMIT,
+ &max_destid);
+ max_destid &= RIO_RT_MAX_DESTID;
+ }
+
+ if (pef & RIO_PEF_EXT_RT) {
+ ext_cfg = 0x80000000;
+ id_inc = 4;
+ port_sel = (RIO_INVALID_ROUTE << 24) |
+ (RIO_INVALID_ROUTE << 16) |
+ (RIO_INVALID_ROUTE << 8) |
+ RIO_INVALID_ROUTE;
+ }
+
+ for (i = 0; i <= max_destid;) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_DESTID_SEL_CSR,
+ ext_cfg | i);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_PORT_SEL_CSR,
+ port_sel);
+ i += id_inc;
+ }
+ }
+
+ udelay(10);
+ return 0;
+}
+
static void rio_fixup_device(struct rio_dev *dev)
{
}
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/rio.h w33r7d/drivers/rapidio/rio.h
--- w33r7c/drivers/rapidio/rio.h 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/drivers/rapidio/rio.h 2010-02-22 11:06:24.035348000 -0500
@@ -21,6 +21,14 @@ extern u32 rio_mport_get_feature(struct
extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
extern int rio_enum_mport(struct rio_mport *mport);
extern int rio_disc_mport(struct rio_mport *mport);
+extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid,
+ u8 hopcount, u16 table, u16 route_destid,
+ u8 route_port);
+extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid,
+ u8 hopcount, u16 table, u16 route_destid,
+ u8 *route_port);
+extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
+ u8 hopcount, u16 table);
/* Structures internal to the RIO core code */
extern struct device_attribute rio_dev_attrs[];
@@ -30,9 +38,9 @@ extern struct rio_route_ops __start_rio_
extern struct rio_route_ops __end_rio_route_ops[];
/* Helpers internal to the RIO core code */
-#define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \
- static struct rio_route_ops __rio_route_ops __used \
- __section(section)= { vid, did, add_hook, get_hook };
+#define DECLARE_RIO_ROUTE_SECTION(section, name, vid, did, add_hook, get_hook, clr_hook) \
+ static const struct rio_route_ops __rio_route_##name __used \
+ __section(section) = { vid, did, add_hook, get_hook, clr_hook };
/**
* DECLARE_RIO_ROUTE_OPS - Registers switch routing operations
@@ -47,9 +55,9 @@ extern struct rio_route_ops __end_rio_ro
* rio_route_ops is initialized with the ops and placed into a
* RIO-specific kernel section.
*/
-#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \
- DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
- vid, did, add_hook, get_hook)
+#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook, clr_hook) \
+ DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, vid##did, \
+ vid, did, add_hook, get_hook, clr_hook)
#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/switches/Makefile w33r7d/drivers/rapidio/switches/Makefile
--- w33r7c/drivers/rapidio/switches/Makefile 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/drivers/rapidio/switches/Makefile 2010-02-22 11:06:24.065326000 -0500
@@ -2,4 +2,4 @@
# Makefile for RIO switches
#
-obj-$(CONFIG_RAPIDIO) += tsi500.o
+obj-$(CONFIG_RAPIDIO) += tsi500.o tsi568.o tsi57x.o idtcps.o
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/switches/idtcps.c w33r7d/drivers/rapidio/switches/idtcps.c
--- w33r7c/drivers/rapidio/switches/idtcps.c 1969-12-31 19:00:00.000000000 -0500
+++ w33r7d/drivers/rapidio/switches/idtcps.c 2010-02-22 11:06:24.069310000 -0500
@@ -0,0 +1,84 @@
+/*
+ * IDT CPS RapidIO switches support
+ *
+ * Copyright 2009 Integrated Device Technology, Inc.
+ *
+ * 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/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+#include "../rio.h"
+
+static int
+idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 route_port)
+{
+ u32 result;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
+
+ rio_mport_read_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
+
+ result = (0xffffff00 & result) | (u32)route_port;
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_PORT_SEL_CSR, result);
+ }
+
+ return 0;
+}
+
+static int
+idtcps_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 *route_port)
+{
+ u32 result;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
+
+ rio_mport_read_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
+
+ *route_port = (u8)result;
+ }
+
+ return 0;
+}
+
+static int
+idtcps_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table)
+{
+ u32 i;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ for (i = 0x80000000; i <= 0x800000ff;) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_DESTID_SEL_CSR, i);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ RIO_STD_RTE_CONF_PORT_SEL_CSR,
+ (RIO_INVALID_ROUTE << 24) |
+ (RIO_INVALID_ROUTE << 16) |
+ (RIO_INVALID_ROUTE << 8) | RIO_INVALID_ROUTE);
+ i += 4;
+ }
+ }
+
+ return 0;
+}
+
+DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS6Q, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS8, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS10Q, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS12, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS16, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDT70K200, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/switches/tsi500.c w33r7d/drivers/rapidio/switches/tsi500.c
--- w33r7c/drivers/rapidio/switches/tsi500.c 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/drivers/rapidio/switches/tsi500.c 2010-02-22 11:06:24.070325000 -0500
@@ -57,4 +57,4 @@ tsi500_route_get_entry(struct rio_mport
return ret;
}
-DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry, NULL);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/switches/tsi568.c w33r7d/drivers/rapidio/switches/tsi568.c
--- w33r7c/drivers/rapidio/switches/tsi568.c 1969-12-31 19:00:00.000000000 -0500
+++ w33r7d/drivers/rapidio/switches/tsi568.c 2010-02-22 11:06:24.072314000 -0500
@@ -0,0 +1,106 @@
+/*
+ * RapidIO Tsi568 switch support
+ *
+ * Copyright 2009-2010 Integrated Device Technology, Inc.
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+#include <linux/delay.h>
+#include "../rio.h"
+
+/* Global (broadcast) route registers */
+#define SPBC_ROUTE_CFG_DESTID 0x10070
+#define SPBC_ROUTE_CFG_PORT 0x10074
+
+/* Per port route registers */
+#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
+#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
+
+static int
+tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 route_port)
+{
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_DESTID, route_destid);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_PORT, route_port);
+ } else {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_DESTID(table),
+ route_destid);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_PORT(table), route_port);
+ }
+
+ udelay(10);
+
+ return 0;
+}
+
+static int
+tsi568_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 *route_port)
+{
+ int ret = 0;
+ u32 result;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_DESTID, route_destid);
+ rio_mport_read_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_PORT, &result);
+ } else {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_DESTID(table),
+ route_destid);
+ rio_mport_read_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_PORT(table), &result);
+ }
+
+ *route_port = result;
+ if (*route_port > 15)
+ ret = -1;
+
+ return ret;
+}
+
+static int
+tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table)
+{
+ u32 route_idx;
+ u32 lut_size;
+
+ lut_size = (mport->sys_size) ? 0x1ff : 0xff;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_DESTID, 0x80000000);
+ for (route_idx = 0; route_idx <= lut_size; route_idx++)
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_PORT,
+ RIO_INVALID_ROUTE);
+ } else {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_DESTID(table),
+ 0x80000000);
+ for (route_idx = 0; route_idx <= lut_size; route_idx++)
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_PORT(table),
+ RIO_INVALID_ROUTE);
+ }
+
+ return 0;
+}
+
+DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_route_add_entry, tsi568_route_get_entry, tsi568_route_clr_table);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/drivers/rapidio/switches/tsi57x.c w33r7d/drivers/rapidio/switches/tsi57x.c
--- w33r7c/drivers/rapidio/switches/tsi57x.c 1969-12-31 19:00:00.000000000 -0500
+++ w33r7d/drivers/rapidio/switches/tsi57x.c 2010-02-22 11:06:24.074316000 -0500
@@ -0,0 +1,106 @@
+/*
+ * RapidIO Tsi57x switch family support
+ *
+ * Copyright 2009 Integrated Device Technology, Inc.
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+#include <linux/delay.h>
+#include "../rio.h"
+
+/* Global (broadcast) route registers */
+#define SPBC_ROUTE_CFG_DESTID 0x10070
+#define SPBC_ROUTE_CFG_PORT 0x10074
+
+/* Per port route registers */
+#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
+#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
+
+static int
+tsi57x_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 route_port)
+{
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_DESTID, route_destid);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_PORT, route_port);
+ } else {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_DESTID(table), route_destid);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_PORT(table), route_port);
+ }
+
+ udelay(10);
+
+ return 0;
+}
+
+static int
+tsi57x_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 *route_port)
+{
+ int ret = 0;
+ u32 result;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ /* Use local RT of the ingress port to avoid possible
+ race condition */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ RIO_SWP_INFO_CAR, &result);
+ table = (result & RIO_SWP_INFO_PORT_NUM_MASK);
+ }
+
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_DESTID(table), route_destid);
+ rio_mport_read_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_PORT(table), &result);
+
+ *route_port = (u8)result;
+ if (*route_port > 15)
+ ret = -1;
+
+ return ret;
+}
+
+static int
+tsi57x_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table)
+{
+ u32 route_idx;
+ u32 lut_size;
+
+ lut_size = (mport->sys_size) ? 0x1ff : 0xff;
+
+ if (table == RIO_GLOBAL_TABLE) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_DESTID, 0x80000000);
+ for (route_idx = 0; route_idx <= lut_size; route_idx++)
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPBC_ROUTE_CFG_PORT,
+ RIO_INVALID_ROUTE);
+ } else {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_DESTID(table), 0x80000000);
+ for (route_idx = 0; route_idx <= lut_size; route_idx++)
+ rio_mport_write_config_32(mport, destid, hopcount,
+ SPP_ROUTE_CFG_PORT(table) , RIO_INVALID_ROUTE);
+ }
+
+ return 0;
+}
+
+DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
+DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/include/linux/rio.h w33r7d/include/linux/rio.h
--- w33r7c/include/linux/rio.h 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/include/linux/rio.h 2010-02-22 11:06:24.105282000 -0500
@@ -213,6 +213,7 @@ struct rio_net {
* @route_table: Copy of switch routing table
* @add_entry: Callback for switch-specific route add function
* @get_entry: Callback for switch-specific route get function
+ * @clr_table: Callback for switch-specific clear route table function
*/
struct rio_switch {
struct list_head node;
@@ -224,6 +225,8 @@ struct rio_switch {
u16 table, u16 route_destid, u8 route_port);
int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 * route_port);
+ int (*clr_table) (struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table);
};
/* Low-level architecture-dependent routines */
@@ -307,6 +310,7 @@ struct rio_device_id {
* @did: RIO device ID
* @add_hook: Callback that adds a route entry
* @get_hook: Callback that gets a route entry
+ * @clr_hook: Callback that clears a switch route table (may be NULL)
*
* Defines the operations that are necessary to manipulate the route
* tables for a particular RIO switch device.
@@ -317,6 +321,8 @@ struct rio_route_ops {
u16 table, u16 route_destid, u8 route_port);
int (*get_hook) (struct rio_mport * mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 * route_port);
+ int (*clr_hook) (struct rio_mport *mport, u16 destid, u8 hopcount,
+ u16 table);
};
/* Architecture and hardware-specific functions */
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/include/linux/rio_ids.h w33r7d/include/linux/rio_ids.h
--- w33r7c/include/linux/rio_ids.h 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/include/linux/rio_ids.h 2010-02-22 11:06:24.241142000 -0500
@@ -20,5 +20,19 @@
#define RIO_VID_TUNDRA 0x000d
#define RIO_DID_TSI500 0x0500
+#define RIO_DID_TSI568 0x0568
+#define RIO_DID_TSI572 0x0572
+#define RIO_DID_TSI574 0x0574
+#define RIO_DID_TSI576 0x0578 /* Same ID as Tsi578 */
+#define RIO_DID_TSI577 0x0577
+#define RIO_DID_TSI578 0x0578
+
+#define RIO_VID_IDT 0x0038
+#define RIO_DID_IDT70K200 0x0310
+#define RIO_DID_IDTCPS8 0x035c
+#define RIO_DID_IDTCPS12 0x035d
+#define RIO_DID_IDTCPS16 0x035b
+#define RIO_DID_IDTCPS6Q 0x035f
+#define RIO_DID_IDTCPS10Q 0x035e
#endif /* LINUX_RIO_IDS_H */
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7c/include/linux/rio_regs.h w33r7d/include/linux/rio_regs.h
--- w33r7c/include/linux/rio_regs.h 2010-02-06 17:17:12.000000000 -0500
+++ w33r7d/include/linux/rio_regs.h 2010-02-22 11:06:24.248134000 -0500
@@ -39,6 +39,8 @@
#define RIO_PEF_INB_MBOX2 0x00200000 /* [II] Mailbox 2 */
#define RIO_PEF_INB_MBOX3 0x00100000 /* [II] Mailbox 3 */
#define RIO_PEF_INB_DOORBELL 0x00080000 /* [II] Doorbells */
+#define RIO_PEF_EXT_RT 0x00000200 /* [III, 1.3] Extended route table support */
+#define RIO_PEF_STD_RT 0x00000100 /* [III, 1.3] Standard route table support */
#define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */
#define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */
#define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */
@@ -91,7 +93,10 @@
#define RIO_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */
#define RIO_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */
- /* 0x20-0x3c *//* Reserved */
+ /* 0x20-0x30 *//* Reserved */
+
+#define RIO_SWITCH_RT_LIMIT 0x34 /* [III, 1.3] Switch Route Table Destination ID Limit CAR */
+#define RIO_RT_MAX_DESTID 0x0000ffff
#define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */
#define RIO_MBOX0_AVAIL 0x80000000 /* [II] Mbox 0 avail */
@@ -153,7 +158,11 @@
#define RIO_HOST_DID_LOCK_CSR 0x68 /* [III] Host Base Device ID Lock CSR */
#define RIO_COMPONENT_TAG_CSR 0x6c /* [III] Component Tag CSR */
- /* 0x70-0xf8 *//* Reserved */
+#define RIO_STD_RTE_CONF_DESTID_SEL_CSR 0x70
+#define RIO_STD_RTE_CONF_PORT_SEL_CSR 0x74
+#define RIO_STD_RTE_DEFAULT_PORT 0x78
+
+ /* 0x7c-0xf8 *//* Reserved */
/* 0x100-0xfff8 *//* [I] Extended Features Space */
/* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */
@@ -186,6 +195,7 @@
#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */
#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */
#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */
+#define RIO_EFB_SER_EP_FREC_ID 0x0009 /* [VI] LP/Serial EP Free Recovery Devices */
/*
* Physical 8/16 LP-LVDS
---
Important Notice: This message is intended for the use of the individual to whom it is addressed and may contain information which is privileged, confidential and/or exempt from disclosure under applicable law. If the reader of this message is not the intended recipient, or is not the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender immediately by telephone or return e-mail and delete the original message from your systems. Thank you.
^ permalink raw reply
* [PATCH 6/7] RapidIO: Add RX/TX enable for SRIO port
From: Alexandre Bounine @ 2010-02-24 15:34 UTC (permalink / raw)
To: mporter; +Cc: abounine, linuxppc-dev, linux-kernel, thomas.moll.ext,
thomas.moll
From: Thomas Moll <thomas.moll@sysgo.com>
Add the functionality to enable Input receiver and Output
transmitter of every port, to allow non-maintenance traffic.
Signed-off-by: Thomas Moll <thomas.moll@sysgo.com>
---
drivers/rapidio/Kconfig | 11 ++++++
drivers/rapidio/rio-scan.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-
include/linux/rio_regs.h | 5 ++
3 files changed, 94 insertions(+), 1 deletion(-)
diff -purN linux-base/drivers/rapidio/Kconfig linux-new/drivers/rapidio/Kconfig
--- linux-base/drivers/rapidio/Kconfig 2010-02-22 10:44:47.000000000 +0100
+++ linux-new/drivers/rapidio/Kconfig 2010-02-22 12:36:20.000000000 +0100
@@ -8,3 +8,14 @@ config RAPIDIO_DISC_TIMEOUT
---help---
Amount of time a discovery node waits for a host to complete
enumeration before giving up.
+
+config RAPIDIO_ENABLE_RX_TX_PORTS
+ bool "Enable RapidIO Input/Output Ports"
+ depends on RAPIDIO
+ ---help---
+ The RapidIO specification describes a Output port transmit
+ enable and a Input port receive enable. The recommended state
+ for Input ports and Output ports should be disabled. When
+ this switch is set the RapidIO subsystem will enable all
+ ports for Input/Output direction to allow other traffic
+ than Maintenance transfers.
diff -purN linux-base/drivers/rapidio/rio-scan.c linux-new/drivers/rapidio/rio-scan.c
--- linux-base/drivers/rapidio/rio-scan.c 2010-02-22 10:48:15.000000000 +0100
+++ linux-new/drivers/rapidio/rio-scan.c 2010-02-22 13:42:08.000000000 +0100
@@ -8,6 +8,10 @@
* Alex Bounine <alexandre.bounine@idt.com>
* - Added Port-Write/Error Management initialization and handling
*
+ * Copyright 2009 Sysgo AG
+ * Thomas Moll <thomas.moll@sysgo.com>
+ * - Added Input- Output- enable functionality, to allow full communication
+ *
* 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
@@ -328,6 +332,65 @@ static int __devinit rio_add_device(stru
}
/**
+ * rio_enable_rx_tx_port - enable input reciever and output transmitter of
+ * given port
+ * @port: Master port associated with the RIO network
+ * @local: local=1 select local port otherwise a far device is reached
+ * @destid: Destination ID of the device to check host bit
+ * @hopcount: Number of hops to reach the target
+ * @port_num: Port (-number on switch) to enable on a far end device
+ *
+ * Returns 0 or 1 from on General Control Command and Status Register
+ * (EXT_PTR+0x3C)
+ */
+inline int rio_enable_rx_tx_port(struct rio_mport *port,
+ int local, u16 destid,
+ u8 hopcount, u8 port_num) {
+#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
+ u32 regval;
+ u32 ext_ftr_ptr;
+
+ /*
+ * enable rx input tx output port
+ */
+ pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
+ "%d, port_num = %d)\n", local, destid, hopcount, port_num);
+
+ ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
+
+ if (local) {
+ rio_local_read_config_32(port, ext_ftr_ptr +
+ RIO_PORT_N_CTL_CSR(0),
+ ®val);
+ } else {
+ if (rio_mport_read_config_32(port, destid, hopcount,
+ ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), ®val) < 0)
+ return -EIO;
+ }
+
+ if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
+ /* serial */
+ regval = regval | RIO_PORT_N_CTL_EN_RX_SER
+ | RIO_PORT_N_CTL_EN_TX_SER;
+ } else {
+ /* parallel */
+ regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
+ | RIO_PORT_N_CTL_EN_TX_PAR;
+ }
+
+ if (local) {
+ rio_local_write_config_32(port, ext_ftr_ptr +
+ RIO_PORT_N_CTL_CSR(0), regval);
+ } else {
+ if (rio_mport_write_config_32(port, destid, hopcount,
+ ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
+ return -EIO;
+ }
+#endif
+ return 0;
+}
+
+/**
* rio_setup_device- Allocates and sets up a RIO device
* @net: RIO network
* @port: Master port to send transactions
@@ -430,9 +493,14 @@ static struct rio_dev __devinit *rio_set
list_add_tail(&rswitch->node, &rio_switches);
- } else
+ } else {
+ if (do_enum)
+ /*Enable Input Output Port (transmitter reviever)*/
+ rio_enable_rx_tx_port(port, 0, destid, hopcount, 0);
+
dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id,
rdev->destid);
+ }
rdev->dev.bus = &rio_bus_type;
@@ -740,6 +808,11 @@ static int __devinit rio_enum_peer(struc
rio_name(rdev), rdev->vid, rdev->did, num_ports);
sw_destid = next_destid;
for (port_num = 0; port_num < num_ports; port_num++) {
+ /*Enable Input Output Port (transmitter reviever)*/
+ rio_enable_rx_tx_port(port, 0,
+ RIO_ANY_DESTID(port->sys_size),
+ hopcount, port_num);
+
if (sw_inport == port_num) {
rdev->rswitch->port_ok |= (1 << port_num);
continue;
@@ -1085,6 +1158,10 @@ int __devinit rio_enum_mport(struct rio_
rc = -ENOMEM;
goto out;
}
+
+ /* Enable Input Output Port (transmitter reviever) */
+ rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
+
if (rio_enum_peer(net, mport, 0) < 0) {
/* A higher priority host won enumeration, bail. */
printk(KERN_INFO
diff -purN linux-base/include/linux/rio_regs.h linux-new/include/linux/rio_regs.h
--- linux-base/include/linux/rio_regs.h 2010-02-22 10:48:15.000000000 +0100
+++ linux-new/include/linux/rio_regs.h 2010-02-22 12:38:57.000000000 +0100
@@ -242,7 +242,12 @@
#define RIO_PORT_N_CTL_PWIDTH 0xc0000000
#define RIO_PORT_N_CTL_PWIDTH_1 0x00000000
#define RIO_PORT_N_CTL_PWIDTH_4 0x40000000
+#define RIO_PORT_N_CTL_P_TYP_SER 0x00000001
#define RIO_PORT_N_CTL_LOCKOUT 0x00000002
+#define RIO_PORT_N_CTL_EN_RX_SER 0x00200000
+#define RIO_PORT_N_CTL_EN_TX_SER 0x00400000
+#define RIO_PORT_N_CTL_EN_RX_PAR 0x08000000
+#define RIO_PORT_N_CTL_EN_TX_PAR 0x40000000
/*
* Error Management Extensions (RapidIO 1.3+, Part 8)
---
Important Notice: This message is intended for the use of the individual to whom it is addressed and may contain information which is privileged, confidential and/or exempt from disclosure under applicable law. If the reader of this message is not the intended recipient, or is not the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender immediately by telephone or return e-mail and delete the original message from your systems. Thank you.
^ permalink raw reply
* [PATCH 5/7] powerpc/85xx: Add MChk handler for SRIO port
From: Alexandre Bounine @ 2010-02-24 15:30 UTC (permalink / raw)
To: mporter; +Cc: abounine, linuxppc-dev, linux-kernel, thomas.moll.ext,
thomas.moll
From: Alexandre Bounine <alexandre.bounine@idt.com>
Add Machine Check exception handling into RapidIO port driver
for Freescale SoCs (MPC85xx).
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Tested-by: Thomas Moll <thomas.moll@sysgo.com>
---
fsl_rio.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 70 insertions(+), 4 deletions(-)
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/arch/powerpc/sysdev/fsl_rio.c w33r7b/arch/powerpc/sysdev/fsl_rio.c
--- w33r7a/arch/powerpc/sysdev/fsl_rio.c 2010-02-12 11:03:23.425826000 -0500
+++ w33r7b/arch/powerpc/sysdev/fsl_rio.c 2010-02-12 13:46:57.558951000 -0500
@@ -31,6 +31,8 @@
#include <linux/kfifo.h>
#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/uaccess.h>
#undef DEBUG_PW /* Port-Write debugging */
@@ -46,6 +48,8 @@
#define RIO_ESCSR 0x158
#define RIO_CCSR 0x15c
#define RIO_LTLEDCSR 0x0608
+#define RIO_LTLEDCSR_IER 0x80000000
+#define RIO_LTLEDCSR_PRT 0x01000000
#define RIO_LTLEECSR 0x060c
#define RIO_EPWISR 0x10010
#define RIO_ISR_AACR 0x10120
@@ -213,6 +217,54 @@ struct rio_priv {
spinlock_t pw_fifo_lock;
};
+#define __fsl_read_rio_config(x, addr, err, op) \
+ __asm__ __volatile__( \
+ "1: "op" %1,0(%2)\n" \
+ " eieio\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %1,-1\n" \
+ " li %0,%3\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (err), "=r" (x) \
+ : "b" (addr), "i" (-EFAULT), "0" (err))
+
+static void __iomem *rio_regs_win;
+
+static int (*saved_mcheck_exception)(struct pt_regs *regs);
+
+static int fsl_rio_mcheck_exception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *entry = NULL;
+ unsigned long reason = (mfspr(SPRN_MCSR) & MCSR_MASK);
+
+ if (reason & MCSR_BUS_RBERR) {
+ reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
+ if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
+ /* Check if we are prepared to handle this fault */
+ entry = search_exception_tables(regs->nip);
+ if (entry) {
+ pr_debug("RIO: %s - MC Exception handled\n",
+ __func__);
+ out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
+ 0);
+ regs->msr |= MSR_RI;
+ regs->nip = entry->fixup;
+ return 1;
+ }
+ }
+ }
+
+ if (saved_mcheck_exception)
+ return saved_mcheck_exception(regs);
+ else
+ return cur_cpu_spec->machine_check(regs);
+}
+
/**
* fsl_rio_doorbell_send - Send a MPC85xx doorbell message
* @mport: RapidIO master port info
@@ -313,6 +365,7 @@ fsl_rio_config_read(struct rio_mport *mp
{
struct rio_priv *priv = mport->priv;
u8 *data;
+ u32 rval, err = 0;
pr_debug
("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
@@ -323,17 +376,24 @@ fsl_rio_config_read(struct rio_mport *mp
data = (u8 *) priv->maint_win + offset;
switch (len) {
case 1:
- *val = in_8((u8 *) data);
+ __fsl_read_rio_config(rval, data, err, "lbz");
break;
case 2:
- *val = in_be16((u16 *) data);
+ __fsl_read_rio_config(rval, data, err, "lhz");
break;
default:
- *val = in_be32((u32 *) data);
+ __fsl_read_rio_config(rval, data, err, "lwz");
break;
}
- return 0;
+ if (err) {
+ pr_debug("RIO: cfg_read error %d for %x:%x:%x\n",
+ err, destid, hopcount, offset);
+ }
+
+ *val = rval;
+
+ return err;
}
/**
@@ -1364,6 +1424,7 @@ int fsl_rio_setup(struct of_device *dev)
rio_register_mport(port);
priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
+ rio_regs_win = priv->regs_win;
/* Probe the master port phy type */
ccsr = in_be32(priv->regs_win + RIO_CCSR);
@@ -1432,6 +1493,11 @@ int fsl_rio_setup(struct of_device *dev)
fsl_rio_doorbell_init(port);
fsl_rio_port_write_init(port);
+ saved_mcheck_exception = ppc_md.machine_check_exception;
+ ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
+ /* Ensure that RFXE is set */
+ mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
+
return 0;
err:
iounmap(priv->regs_win);
---
Important Notice: This message is intended for the use of the individual to whom it is addressed and may contain information which is privileged, confidential and/or exempt from disclosure under applicable law. If the reader of this message is not the intended recipient, or is not the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender immediately by telephone or return e-mail and delete the original message from your systems. Thank you.
^ permalink raw reply
* [PATCH 4/7] powerpc/85xx: Add Port-Write message handler for SRIO port
From: Alexandre Bounine @ 2010-02-24 15:27 UTC (permalink / raw)
To: mporter; +Cc: linuxppc-dev, linux-kernel, thomas.moll.ext, thomas.moll
From: Alexandre Bounine <alexandre.bounine@idt.com>
Add RapidIO Port-Write message handler for Freescale SoCs with RapidIO port.
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Tested-by: Thomas Moll <thomas.moll@sysgo.com>
---
fsl_rio.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 260 insertions(+), 3 deletions(-)
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/arch/powerpc/sysdev/fsl_rio.c w33r7b/arch/powerpc/sysdev/fsl_rio.c
--- w33r7a/arch/powerpc/sysdev/fsl_rio.c 2010-02-06 17:17:12.000000000 -0500
+++ w33r7b/arch/powerpc/sysdev/fsl_rio.c 2010-02-12 10:43:03.297481000 -0500
@@ -1,6 +1,11 @@
/*
* Freescale MPC85xx/MPC86xx RapidIO support
*
+ * Copyright 2009 Integrated Device Technology, Inc.
+ * Alex Bounine <alexandre.bounine@idt.com>
+ * - Added Port-Write message handling
+ * - Added Machine Check exception handling
+ *
* Copyright (C) 2007, 2008 Freescale Semiconductor, Inc.
* Zhang Wei <wei.zhang@freescale.com>
*
@@ -23,19 +28,26 @@
#include <linux/rio_drv.h>
#include <linux/of_platform.h>
#include <linux/delay.h>
+#include <linux/kfifo.h>
#include <asm/io.h>
+#undef DEBUG_PW /* Port-Write debugging */
+
/* RapidIO definition irq, which read from OF-tree */
#define IRQ_RIO_BELL(m) (((struct rio_priv *)(m->priv))->bellirq)
#define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq)
#define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq)
+#define IRQ_RIO_PW(m) (((struct rio_priv *)(m->priv))->pwirq)
#define RIO_ATMU_REGS_OFFSET 0x10c00
#define RIO_P_MSG_REGS_OFFSET 0x11000
#define RIO_S_MSG_REGS_OFFSET 0x13000
#define RIO_ESCSR 0x158
#define RIO_CCSR 0x15c
+#define RIO_LTLEDCSR 0x0608
+#define RIO_LTLEECSR 0x060c
+#define RIO_EPWISR 0x10010
#define RIO_ISR_AACR 0x10120
#define RIO_ISR_AACR_AA 0x1 /* Accept All ID */
#define RIO_MAINT_WIN_SIZE 0x400000
@@ -54,6 +66,18 @@
#define RIO_MSG_ISR_QFI 0x00000010
#define RIO_MSG_ISR_DIQI 0x00000001
+#define RIO_IPWMR_SEN 0x00100000
+#define RIO_IPWMR_QFIE 0x00000100
+#define RIO_IPWMR_EIE 0x00000020
+#define RIO_IPWMR_CQ 0x00000002
+#define RIO_IPWMR_PWE 0x00000001
+
+#define RIO_IPWSR_QF 0x00100000
+#define RIO_IPWSR_TE 0x00000080
+#define RIO_IPWSR_QFI 0x00000010
+#define RIO_IPWSR_PWD 0x00000008
+#define RIO_IPWSR_PWB 0x00000004
+
#define RIO_MSG_DESC_SIZE 32
#define RIO_MSG_BUFFER_SIZE 4096
#define RIO_MIN_TX_RING_SIZE 2
@@ -120,7 +144,7 @@ struct rio_msg_regs {
u32 pad10[26];
u32 pwmr;
u32 pwsr;
- u32 pad11;
+ u32 epwqbar;
u32 pwqbar;
};
@@ -159,6 +183,14 @@ struct rio_msg_rx_ring {
void *dev_id;
};
+struct rio_port_write_msg {
+ void *virt;
+ dma_addr_t phys;
+ u32 msg_count;
+ u32 err_count;
+ u32 discard_count;
+};
+
struct rio_priv {
struct device *dev;
void __iomem *regs_win;
@@ -171,9 +203,14 @@ struct rio_priv {
struct rio_dbell_ring dbell_ring;
struct rio_msg_tx_ring msg_tx_ring;
struct rio_msg_rx_ring msg_rx_ring;
+ struct rio_port_write_msg port_write_msg;
int bellirq;
int txirq;
int rxirq;
+ int pwirq;
+ struct work_struct pw_work;
+ struct kfifo pw_fifo;
+ spinlock_t pw_fifo_lock;
};
/**
@@ -929,6 +966,223 @@ static int fsl_rio_doorbell_init(struct
return rc;
}
+/**
+ * fsl_rio_port_write_handler - MPC85xx port write interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ *
+ * Handles port write interrupts. Parses a list of registered
+ * port write event handlers and executes a matching event handler.
+ */
+static irqreturn_t
+fsl_rio_port_write_handler(int irq, void *dev_instance)
+{
+ u32 ipwmr, ipwsr;
+ struct rio_mport *port = (struct rio_mport *)dev_instance;
+ struct rio_priv *priv = port->priv;
+ u32 epwisr, tmp;
+
+ ipwmr = in_be32(&priv->msg_regs->pwmr);
+ ipwsr = in_be32(&priv->msg_regs->pwsr);
+
+ epwisr = in_be32(priv->regs_win + RIO_EPWISR);
+ if (epwisr & 0x80000000) {
+ tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
+ pr_info("RIO_LTLEDCSR = 0x%x\n", tmp);
+ out_be32(priv->regs_win + RIO_LTLEDCSR, 0);
+ }
+
+ if (!(epwisr & 0x00000001))
+ return IRQ_HANDLED;
+
+#ifdef DEBUG_PW
+ pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr);
+ if (ipwsr & RIO_IPWSR_QF)
+ pr_debug(" QF");
+ if (ipwsr & RIO_IPWSR_TE)
+ pr_debug(" TE");
+ if (ipwsr & RIO_IPWSR_QFI)
+ pr_debug(" QFI");
+ if (ipwsr & RIO_IPWSR_PWD)
+ pr_debug(" PWD");
+ if (ipwsr & RIO_IPWSR_PWB)
+ pr_debug(" PWB");
+ pr_debug(" )\n");
+#endif
+ out_be32(&priv->msg_regs->pwsr,
+ ipwsr & (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));
+
+ if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
+ priv->port_write_msg.err_count++;
+ pr_info("RIO: Port-Write Transaction Err (%d)\n",
+ priv->port_write_msg.err_count);
+ }
+ if (ipwsr & RIO_IPWSR_PWD) {
+ priv->port_write_msg.discard_count++;
+ pr_info("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
+ priv->port_write_msg.discard_count);
+ }
+
+ /* Schedule deferred processing if PW was received */
+ if (ipwsr & RIO_IPWSR_QFI) {
+ /* Save PW message (if there is room in FIFO),
+ * otherwise discard it.
+ */
+ if (kfifo_avail(&priv->pw_fifo) >= RIO_PW_MSG_SIZE) {
+ priv->port_write_msg.msg_count++;
+ kfifo_in(&priv->pw_fifo, priv->port_write_msg.virt,
+ RIO_PW_MSG_SIZE);
+ } else {
+ priv->port_write_msg.discard_count++;
+ pr_info("RIO: ISR Discarded Port-Write Msg(s) (%d)\n",
+ priv->port_write_msg.discard_count);
+ }
+ schedule_work(&priv->pw_work);
+ }
+
+ /* Issue Clear Queue command. This allows another
+ * port-write to be received.
+ */
+ out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ);
+
+ return IRQ_HANDLED;
+}
+
+static void fsl_pw_dpc(struct work_struct *work)
+{
+ struct rio_priv *priv = container_of(work, struct rio_priv, pw_work);
+ unsigned long flags;
+ u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)];
+
+ /*
+ * Process port-write messages
+ */
+ spin_lock_irqsave(&priv->pw_fifo_lock, flags);
+ while (kfifo_out(&priv->pw_fifo, (unsigned char *)msg_buffer,
+ RIO_PW_MSG_SIZE)) {
+ /* Process one message */
+ spin_unlock_irqrestore(&priv->pw_fifo_lock, flags);
+#ifdef DEBUG_PW
+ {
+ u32 i;
+ pr_debug("%s : Port-Write Message:", __func__);
+ for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) {
+ if ((i%4) == 0)
+ pr_debug("\n0x%02x: 0x%08x", i*4,
+ msg_buffer[i]);
+ else
+ pr_debug(" 0x%08x", msg_buffer[i]);
+ }
+ pr_debug("\n");
+ }
+#endif
+ /* Pass the port-write message to RIO core for processing */
+ rio_inb_pwrite_handler(msg_buffer);
+ spin_lock_irqsave(&priv->pw_fifo_lock, flags);
+ }
+ spin_unlock_irqrestore(&priv->pw_fifo_lock, flags);
+}
+
+/**
+ * fsl_rio_pw_enable - enable/disable port-write interface init
+ * @mport: Master port implementing the port write unit
+ * @enable: 1=enable; 0=disable port-write message handling
+ */
+static int fsl_rio_pw_enable(struct rio_mport *mport, int enable)
+{
+ struct rio_priv *priv = mport->priv;
+ u32 rval;
+
+ rval = in_be32(&priv->msg_regs->pwmr);
+
+ if (enable)
+ rval |= RIO_IPWMR_PWE;
+ else
+ rval &= ~RIO_IPWMR_PWE;
+
+ out_be32(&priv->msg_regs->pwmr, rval);
+
+ return 0;
+}
+
+/**
+ * fsl_rio_port_write_init - MPC85xx port write interface init
+ * @mport: Master port implementing the port write unit
+ *
+ * Initializes port write unit hardware and DMA buffer
+ * ring. Called from fsl_rio_setup(). Returns %0 on success
+ * or %-ENOMEM on failure.
+ */
+static int fsl_rio_port_write_init(struct rio_mport *mport)
+{
+ struct rio_priv *priv = mport->priv;
+ int rc = 0;
+
+ /* Following configurations require a disabled port write controller */
+ out_be32(&priv->msg_regs->pwmr,
+ in_be32(&priv->msg_regs->pwmr) & ~RIO_IPWMR_PWE);
+
+ /* Initialize port write */
+ priv->port_write_msg.virt = dma_alloc_coherent(priv->dev,
+ RIO_PW_MSG_SIZE,
+ &priv->port_write_msg.phys, GFP_KERNEL);
+ if (!priv->port_write_msg.virt) {
+ pr_err("RIO: unable allocate port write queue\n");
+ return -ENOMEM;
+ }
+
+ priv->port_write_msg.err_count = 0;
+ priv->port_write_msg.discard_count = 0;
+
+ /* Point dequeue/enqueue pointers at first entry */
+ out_be32(&priv->msg_regs->epwqbar, 0);
+ out_be32(&priv->msg_regs->pwqbar, (u32) priv->port_write_msg.phys);
+
+ pr_debug("EIPWQBAR: 0x%08x IPWQBAR: 0x%08x\n",
+ in_be32(&priv->msg_regs->epwqbar),
+ in_be32(&priv->msg_regs->pwqbar));
+
+ /* Clear interrupt status IPWSR */
+ out_be32(&priv->msg_regs->pwsr,
+ (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));
+
+ /* Configure port write contoller for snooping enable all reporting,
+ clear queue full */
+ out_be32(&priv->msg_regs->pwmr,
+ RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ);
+
+
+ /* Hook up port-write handler */
+ rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, 0,
+ "port-write", (void *)mport);
+ if (rc < 0) {
+ pr_err("MPC85xx RIO: unable to request inbound doorbell irq");
+ goto err_out;
+ }
+
+ INIT_WORK(&priv->pw_work, fsl_pw_dpc);
+ spin_lock_init(&priv->pw_fifo_lock);
+ if (kfifo_alloc(&priv->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
+ pr_err("FIFO allocation failed\n");
+ rc = -ENOMEM;
+ goto err_out_irq;
+ }
+
+ pr_debug("IPWMR: 0x%08x IPWSR: 0x%08x\n",
+ in_be32(&priv->msg_regs->pwmr),
+ in_be32(&priv->msg_regs->pwsr));
+
+ return rc;
+
+err_out_irq:
+ free_irq(IRQ_RIO_PW(mport), (void *)mport);
+err_out:
+ dma_free_coherent(priv->dev, RIO_PW_MSG_SIZE,
+ priv->port_write_msg.virt,
+ priv->port_write_msg.phys);
+ return rc;
+}
+
static char *cmdline = NULL;
static int fsl_rio_get_hdid(int index)
@@ -1066,6 +1320,7 @@ int fsl_rio_setup(struct of_device *dev)
ops->cread = fsl_rio_config_read;
ops->cwrite = fsl_rio_config_write;
ops->dsend = fsl_rio_doorbell_send;
+ ops->pwenable = fsl_rio_pw_enable;
port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
if (!port) {
@@ -1088,11 +1343,12 @@ int fsl_rio_setup(struct of_device *dev)
port->iores.flags = IORESOURCE_MEM;
port->iores.name = "rio_io_win";
+ priv->pwirq = irq_of_parse_and_map(dev->node, 0);
priv->bellirq = irq_of_parse_and_map(dev->node, 2);
priv->txirq = irq_of_parse_and_map(dev->node, 3);
priv->rxirq = irq_of_parse_and_map(dev->node, 4);
- dev_info(&dev->dev, "bellirq: %d, txirq: %d, rxirq %d\n", priv->bellirq,
- priv->txirq, priv->rxirq);
+ dev_info(&dev->dev, "pwirq: %d, bellirq: %d, txirq: %d, rxirq %d\n",
+ priv->pwirq, priv->bellirq, priv->txirq, priv->rxirq);
rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
@@ -1174,6 +1430,7 @@ int fsl_rio_setup(struct of_device *dev)
(law_start + RIO_MAINT_WIN_SIZE) >> 12);
out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b); /* 4k */
fsl_rio_doorbell_init(port);
+ fsl_rio_port_write_init(port);
return 0;
err:
---
Important Notice: This message is intended for the use of the individual to whom it is addressed and may contain information which is privileged, confidential and/or exempt from disclosure under applicable law. If the reader of this message is not the intended recipient, or is not the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender immediately by telephone or return e-mail and delete the original message from your systems. Thank you.
^ permalink raw reply
* [PATCH 3/7] RapidIO: Add Port-Write handling for EM
From: Alexandre Bounine @ 2010-02-24 15:24 UTC (permalink / raw)
To: mporter; +Cc: linuxppc-dev, linux-kernel, thomas.moll.ext, thomas.moll
From: Alexandre Bounine <alexandre.bounine@idt.com>
Add RapidIO Port-Write message handling in the context
of Error Management Extensions Specification Rev.1.3.
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Tested-by: Thomas Moll <thomas.moll@sysgo.com>
---
drivers/rapidio/rio-scan.c | 197 +++++++++++++++++++-----
drivers/rapidio/rio.c | 307 ++++++++++++++++++++++++++++++++++++++
drivers/rapidio/rio.h | 29 +++
drivers/rapidio/switches/tsi568.c | 24 ++
drivers/rapidio/switches/tsi57x.c | 153 ++++++++++++++++++
include/asm-generic/vmlinux.lds.h | 5
include/linux/rio.h | 30 +++
include/linux/rio_drv.h | 6
include/linux/rio_regs.h | 60 +++++++
9 files changed, 771 insertions(+), 40 deletions(-)
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/drivers/rapidio/rio-scan.c w33r7b/drivers/rapidio/rio-scan.c
--- w33r7a/drivers/rapidio/rio-scan.c 2010-02-10 16:25:31.950433000 -0500
+++ w33r7b/drivers/rapidio/rio-scan.c 2010-02-11 14:33:44.796825000 -0500
@@ -4,6 +4,10 @@
* Copyright 2005 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
+ * Copyright 2009 Integrated Device Technology, Inc.
+ * Alex Bounine <alexandre.bounine@idt.com>
+ * - Added Port-Write/Error Management initialization and handling
+ *
* 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
@@ -31,15 +35,16 @@
LIST_HEAD(rio_devices);
static LIST_HEAD(rio_switches);
-#define RIO_ENUM_CMPL_MAGIC 0xdeadbeef
-
static void rio_enum_timeout(unsigned long);
+static void rio_init_em(struct rio_dev *rdev);
+
DEFINE_SPINLOCK(rio_global_list_lock);
static int next_destid = 0;
static int next_switchid = 0;
static int next_net = 0;
+static int next_comptag;
static struct timer_list rio_enum_timer =
TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
@@ -52,13 +57,6 @@ static int rio_mport_phys_table[] = {
-1,
};
-static int rio_sport_phys_table[] = {
- RIO_EFB_PAR_EP_FREE_ID,
- RIO_EFB_SER_EP_FREE_ID,
- RIO_EFB_SER_EP_FREC_ID,
- -1,
-};
-
/**
* rio_get_device_id - Get the base/extended device id for a device
* @port: RIO master port
@@ -119,12 +117,26 @@ static int rio_clear_locks(struct rio_mp
u32 result;
int ret = 0;
- /* Write component tag CSR magic complete value */
- rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR,
- RIO_ENUM_CMPL_MAGIC);
- list_for_each_entry(rdev, &rio_devices, global_list)
- rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR,
- RIO_ENUM_CMPL_MAGIC);
+ /* Assign component tag to all devices */
+ next_comptag = 1;
+ rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++);
+
+ list_for_each_entry(rdev, &rio_devices, global_list) {
+ /* Mark device as discovered */
+ rio_read_config_32(rdev,
+ rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
+ &result);
+ rio_write_config_32(rdev,
+ rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
+ result | RIO_PORT_GEN_DISCOVERED);
+
+ rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag);
+ rdev->comp_tag = next_comptag++;
+ if (next_comptag >= 0x10000) {
+ pr_err("RIO: Component Tag Counter Overflow\n");
+ break;
+ }
+ }
/* Release host device id locks */
rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
@@ -267,6 +279,30 @@ static void rio_route_set_ops(struct rio
}
/**
+ * rio_em_set_ops- Sets Error Managment operations for a particular vendor switch
+ * @rdev: RIO device
+ *
+ * Searches the RIO EM ops table for known switch types. If the vid
+ * and did match a switch table entry, then set the em_init() and
+ * em_handle() ops to the table entry values.
+ */
+static void rio_em_set_ops(struct rio_dev *rdev)
+{
+ struct rio_em_ops *cur = __start_rio_em_ops;
+ struct rio_em_ops *end = __end_rio_em_ops;
+
+ while (cur < end) {
+ if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
+ pr_debug("RIO: adding EM ops for %s\n", rio_name(rdev));
+ rdev->rswitch->em_init = cur->init_hook;
+ rdev->rswitch->em_handle = cur->handler_hook;
+ break;
+ }
+ cur++;
+ }
+}
+
+/**
* rio_add_device- Adds a RIO device to the device model
* @rdev: RIO device
*
@@ -336,8 +372,14 @@ static struct rio_dev __devinit *rio_set
rdev->asm_rev = result >> 16;
rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR,
&rdev->pef);
- if (rdev->pef & RIO_PEF_EXT_FEATURES)
+ if (rdev->pef & RIO_PEF_EXT_FEATURES) {
rdev->efptr = result & 0xffff;
+ rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid,
+ hopcount);
+
+ rdev->em_efptr = rio_mport_get_feature(port, 0, destid,
+ hopcount, RIO_EFB_ERR_MGMNT);
+ }
rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
&rdev->src_ops);
@@ -366,6 +408,7 @@ static struct rio_dev __devinit *rio_set
rswitch->switchid = next_switchid;
rswitch->hopcount = hopcount;
rswitch->destid = destid;
+ rswitch->port_ok = 0;
rswitch->route_table = kzalloc(sizeof(u8)*
RIO_MAX_ROUTE_ENTRIES(port->sys_size),
GFP_KERNEL);
@@ -379,6 +422,7 @@ static struct rio_dev __devinit *rio_set
dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
rdev->rswitch->switchid);
rio_route_set_ops(rdev);
+ rio_em_set_ops(rdev);
if (do_enum && rdev->rswitch->clr_table)
rdev->rswitch->clr_table(port, destid, hopcount,
@@ -429,23 +473,29 @@ cleanup:
*
* Reads the port error status CSR for a particular switch port to
* determine if the port has an active link. Returns
- * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is
+ * %RIO_PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is
* inactive.
*/
static int
rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
{
- u32 result;
+ u32 result = 0;
u32 ext_ftr_ptr;
- int *entry = rio_sport_phys_table;
-
- do {
- if ((ext_ftr_ptr =
- rio_mport_get_feature(port, 0, destid, hopcount, *entry)))
+ ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount, 0);
+ while (ext_ftr_ptr) {
+ rio_mport_read_config_32(port, destid, hopcount,
+ ext_ftr_ptr, &result);
+ result = RIO_GET_BLOCK_ID(result);
+ if ((result == RIO_EFB_SER_EP_FREE_ID) ||
+ (result == RIO_EFB_SER_EP_FREE_ID_V13P) ||
+ (result == RIO_EFB_SER_EP_FREC_ID))
break;
- } while (*++entry >= 0);
+
+ ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount,
+ ext_ftr_ptr);
+ }
if (ext_ftr_ptr)
rio_mport_read_config_32(port, destid, hopcount,
@@ -453,7 +503,38 @@ rio_sport_is_active(struct rio_mport *po
RIO_PORT_N_ERR_STS_CSR(sport),
&result);
- return (result & PORT_N_ERR_STS_PORT_OK);
+ return result & RIO_PORT_N_ERR_STS_PORT_OK;
+}
+
+/**
+ * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port.
+ * @rdev: Pointer to RIO device control structure
+ * @pnum: Switch port number to set LOCKOUT bit
+ * @lock: Operation : set (=1) or clear (=0)
+ */
+static int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock)
+{
+ u8 hopcount = 0xff;
+ u16 destid = rdev->destid;
+ u32 regval;
+
+ if (rdev->rswitch) {
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+ }
+
+ rio_mport_read_config_32(rdev->net->hport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum),
+ ®val);
+ if (lock)
+ regval |= RIO_PORT_N_CTL_LOCKOUT;
+ else
+ regval &= ~RIO_PORT_N_CTL_LOCKOUT;
+
+ rio_mport_write_config_32(rdev->net->hport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum),
+ regval);
+ return 0;
}
/**
@@ -659,8 +740,10 @@ static int __devinit rio_enum_peer(struc
rio_name(rdev), rdev->vid, rdev->did, num_ports);
sw_destid = next_destid;
for (port_num = 0; port_num < num_ports; port_num++) {
- if (sw_inport == port_num)
+ if (sw_inport == port_num) {
+ rdev->rswitch->port_ok |= (1 << port_num);
continue;
+ }
cur_destid = next_destid;
@@ -670,6 +753,7 @@ static int __devinit rio_enum_peer(struc
pr_debug(
"RIO: scanning device on port %d\n",
port_num);
+ rdev->rswitch->port_ok |= (1 << port_num);
rio_route_add_entry(port, rdev->rswitch,
RIO_GLOBAL_TABLE,
RIO_ANY_DESTID(port->sys_size),
@@ -693,9 +777,28 @@ static int __devinit rio_enum_peer(struc
port_num;
}
}
+ } else {
+ /* If switch supports Error Management,
+ * set PORT_LOCKOUT bit for unused port
+ */
+ if (rdev->em_efptr)
+ rio_set_port_lockout(rdev, port_num, 1);
+
+ rdev->rswitch->port_ok &= ~(1 << port_num);
}
}
+ /* Direct Port-write messages to the enumeratiing host */
+ if ((rdev->src_ops & RIO_SRC_OPS_PORT_WRITE) &&
+ (rdev->em_efptr)) {
+ rio_write_config_32(rdev,
+ rdev->em_efptr + RIO_EM_PW_TGT_DEVID,
+ (port->host_deviceid << 16) |
+ (port->sys_size << 15));
+ }
+
+ rio_init_em(rdev);
+
/* Check for empty switch */
if (next_destid == sw_destid) {
next_destid++;
@@ -715,21 +818,16 @@ static int __devinit rio_enum_peer(struc
* rio_enum_complete- Tests if enumeration of a network is complete
* @port: Master port to send transaction
*
- * Tests the Component Tag CSR for presence of the magic enumeration
- * complete flag. Return %1 if enumeration is complete or %0 if
+ * Tests the Component Tag CSR for non-zero value (enumeration
+ * complete flag). Return %1 if enumeration is complete or %0 if
* enumeration is incomplete.
*/
static int rio_enum_complete(struct rio_mport *port)
{
u32 tag_csr;
- int ret = 0;
rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
-
- if (tag_csr == RIO_ENUM_CMPL_MAGIC)
- ret = 1;
-
- return ret;
+ return (tag_csr & 0xffff) ? 1 : 0;
}
/**
@@ -842,7 +940,7 @@ rio_disc_peer(struct rio_net *net, struc
*
* Reads the port error status CSR for the master port to
* determine if the port has an active link. Returns
- * %PORT_N_ERR_STS_PORT_OK if the master port is active
+ * %RIO_PORT_N_ERR_STS_PORT_OK if the master port is active
* or %0 if it is inactive.
*/
static int rio_mport_is_active(struct rio_mport *port)
@@ -863,7 +961,7 @@ static int rio_mport_is_active(struct ri
RIO_PORT_N_ERR_STS_CSR(port->index),
&result);
- return (result & PORT_N_ERR_STS_PORT_OK);
+ return result & RIO_PORT_N_ERR_STS_PORT_OK;
}
/**
@@ -930,6 +1028,32 @@ static void rio_update_route_tables(stru
}
/**
+ * rio_init_em - Initializes RIO Error Management (for switches)
+ * @port: Master port associated with the RIO network
+ *
+ * For each enumerated switch, call device-specific error management
+ * initialization routine (if supplied by the switch driver).
+ */
+static void rio_init_em(struct rio_dev *rdev)
+{
+ if (rio_is_switch(rdev) && (rdev->em_efptr) &&
+ (rdev->rswitch->em_init)) {
+ rdev->rswitch->em_init(rdev);
+ }
+}
+
+/**
+ * rio_pw_enable - Enables/disables port-write handling by a master port
+ * @port: Master port associated with port-write handling
+ * @enable: 1=enable, 0=disable
+ */
+static void rio_pw_enable(struct rio_mport *port, int enable)
+{
+ if (port->ops->pwenable)
+ port->ops->pwenable(port, enable);
+}
+
+/**
* rio_enum_mport- Start enumeration through a master port
* @mport: Master port to send transactions
*
@@ -972,6 +1096,7 @@ int __devinit rio_enum_mport(struct rio_
}
rio_update_route_tables(mport);
rio_clear_locks(mport);
+ rio_pw_enable(mport, 1);
} else {
printk(KERN_INFO "RIO: master port %d link inactive\n",
mport->id);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/drivers/rapidio/rio.c w33r7b/drivers/rapidio/rio.c
--- w33r7a/drivers/rapidio/rio.c 2010-02-09 15:11:09.147959000 -0500
+++ w33r7b/drivers/rapidio/rio.c 2010-02-11 15:04:35.829619000 -0500
@@ -5,6 +5,10 @@
* Copyright 2005 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
+ * Copyright 2009 Integrated Device Technology, Inc.
+ * Alex Bounine <alexandre.bounine@idt.com>
+ * - Added Port-Write/Error Management initialization and handling
+ *
* 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
@@ -333,6 +337,308 @@ int rio_release_outb_dbell(struct rio_de
}
/**
+ * rio_request_inb_pwrite - request inbound port-write message service
+ * @mport: RIO device to which register inbound port-write callback routine
+ * @pwcback: Callback routine to execute when port-write is received
+ *
+ * Binds a port-write callback function to the RapidIO device.
+ * Returns 0 if the request has been satisfied.
+ */
+int rio_request_inb_pwrite(struct rio_dev *rdev,
+ int (*pwcback)(struct rio_dev *rdev, u32* msg, int step))
+{
+ int rc = 0;
+
+ spin_lock(&rio_global_list_lock);
+ if (rdev->pwcback != NULL)
+ rc = -ENOMEM;
+ else
+ rdev->pwcback = pwcback;
+
+ spin_unlock(&rio_global_list_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(rio_request_inb_pwrite);
+
+/**
+ * rio_release_inb_pwrite - release inbound port-write message service
+ * @rdev: RIO device which registered for inbound port-write callback
+ *
+ * Removes callback from the rio_dev structure. Returns 0 if the request
+ * has been satisfied.
+ */
+int rio_release_inb_pwrite(struct rio_dev *rdev)
+{
+ int rc = -ENOMEM;
+
+ spin_lock(&rio_global_list_lock);
+ if (rdev->pwcback) {
+ rdev->pwcback = NULL;
+ rc = 0;
+ }
+
+ spin_unlock(&rio_global_list_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
+
+/**
+ * rio_mport_get_physefb - Helper function that returns register offset
+ * for Physical Layer Extended Features Block.
+ * @rdev: RIO device
+ */
+u32
+rio_mport_get_physefb(struct rio_mport *port, int local,
+ u16 destid, u8 hopcount)
+{
+ u32 ext_ftr_ptr;
+ u32 ftr_header;
+
+ ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, 0);
+
+ while (ext_ftr_ptr) {
+ if (local)
+ rio_local_read_config_32(port, ext_ftr_ptr,
+ &ftr_header);
+ else
+ rio_mport_read_config_32(port, destid, hopcount,
+ ext_ftr_ptr, &ftr_header);
+
+ ftr_header = RIO_GET_BLOCK_ID(ftr_header);
+ switch (ftr_header) {
+
+ case RIO_EFB_SER_EP_ID_V13P:
+ case RIO_EFB_SER_EP_REC_ID_V13P:
+ case RIO_EFB_SER_EP_FREE_ID_V13P:
+ case RIO_EFB_SER_EP_ID:
+ case RIO_EFB_SER_EP_REC_ID:
+ case RIO_EFB_SER_EP_FREE_ID:
+ case RIO_EFB_SER_EP_FREC_ID:
+
+ return ext_ftr_ptr;
+
+ default:
+ break;
+ }
+
+ ext_ftr_ptr = rio_mport_get_efb(port, local, destid,
+ hopcount, ext_ftr_ptr);
+ }
+
+ return ext_ftr_ptr;
+}
+
+/**
+ * rio_get_comptag - Begin or continue searching for a RIO device by component tag
+ * @comp_tag: RIO component tad to match
+ * @from: Previous RIO device found in search, or %NULL for new search
+ *
+ * Iterates through the list of known RIO devices. If a RIO device is
+ * found with a matching @comp_tag, a pointer to its device
+ * structure is returned. Otherwise, %NULL is returned. A new search
+ * is initiated by passing %NULL to the @from argument. Otherwise, if
+ * @from is not %NULL, searches continue from next device on the global
+ * list.
+ */
+static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
+{
+ struct list_head *n;
+ struct rio_dev *rdev;
+
+ WARN_ON(in_interrupt());
+ spin_lock(&rio_global_list_lock);
+ n = from ? from->global_list.next : rio_devices.next;
+
+ while (n && (n != &rio_devices)) {
+ rdev = rio_dev_g(n);
+ if (rdev->comp_tag == comp_tag)
+ goto exit;
+ n = n->next;
+ }
+ rdev = NULL;
+exit:
+ spin_unlock(&rio_global_list_lock);
+ return rdev;
+}
+
+/**
+ * rio_inb_pwrite_handler - process inbound port-write message
+ * @pw_msg: pointer to inbound port-write message
+ *
+ * Processes an inbound port-write message. Returns 0 if the request
+ * has been satisfied.
+ */
+int rio_inb_pwrite_handler(u32 *pw_msg)
+{
+ struct rio_dev *rdev;
+ struct rio_mport *mport;
+ u8 hopcount;
+ u16 destid;
+ u32 regval, err_status;
+ int rc, portnum;
+
+ rdev = rio_get_comptag(pw_msg[0], NULL);
+ if (rdev == NULL) {
+ /* Someting bad here (probably enumeration error) */
+ pr_err("RIO: %s No matching device for CTag 0x%08x\n",
+ __func__, pw_msg[0]);
+ return -EIO;
+ }
+
+ pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev));
+
+#ifdef DEBUG_PW
+ {
+ u32 i;
+ pr_debug("%s : Port-Write Message:", __func__);
+ for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) {
+ if ((i%4) == 0)
+ pr_debug("\n0x%02x: 0x%08x", i, pw_msg[i]);
+ else
+ pr_debug(" 0x%08x", pw_msg[i]);
+ }
+ pr_debug("\n");
+ }
+#endif
+
+ /* Call an external service function (if such is registered
+ * for this device). This may be the service for endpoints that send
+ * device-specific port-write messages. End-point messages expected
+ * to be handled completely by EP specific device driver.
+ * For switches rc==0 signals that no standard processing required.
+ */
+ if (rdev->pwcback != NULL) {
+ rc = rdev->pwcback(rdev, pw_msg, 0);
+ if (rc == 0)
+ return 0;
+ }
+
+ /* For End-point devices processing stops here */
+ if (!(rdev->pef & RIO_PEF_SWITCH))
+ return 0;
+
+ if (rdev->phys_efptr == 0) {
+ pr_err("RIO_PW: Bad switch initialization for %s\n",
+ rio_name(rdev));
+ return 0;
+ }
+
+ mport = rdev->net->hport;
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+
+ /*
+ * Process the port-write notification from switch
+ */
+
+ portnum = pw_msg[2] & 0xFF;
+
+ if (rdev->rswitch->em_handle)
+ rdev->rswitch->em_handle(rdev, portnum);
+
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
+ &err_status);
+ pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status);
+
+ if (pw_msg[1]) {
+ pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n",
+ portnum, pw_msg[1]);
+ /* Clear EM Port N Error Detect CSR */
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0);
+ }
+
+ if (pw_msg[3]) {
+ pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n", pw_msg[3]);
+ /* Clear EM L/T Layer Error Detect CSR */
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0);
+ }
+
+ /* Clear Port Errors */
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
+ err_status & 0x07120204);
+
+ if (rdev->rswitch->port_ok & (1 << portnum)) {
+ if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) {
+ rdev->rswitch->port_ok &= ~(1 << portnum);
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ ®val);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ regval | RIO_PORT_N_CTL_LOCKOUT);
+
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr +
+ RIO_PORT_N_ACK_STS_CSR(portnum),
+ RIO_PORT_N_ACK_CLEAR);
+
+ /* Schedule Extraction Service */
+ pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n",
+ rio_name(rdev), portnum);
+ }
+ } else {
+ if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) {
+ rdev->rswitch->port_ok |= (1 << portnum);
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ ®val);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ regval & ~RIO_PORT_N_CTL_LOCKOUT);
+
+ /* Schedule Insertion Service */
+ pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n",
+ rio_name(rdev), portnum);
+ }
+ }
+
+ /* Clear Port-Write Pending bit */
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
+ RIO_PORT_N_ERR_STS_PW_PEND);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rio_inb_pwrite_handler);
+
+/**
+ * rio_mport_get_efb - get pointer to next extended features block
+ * @port: Master port to issue transaction
+ * @local: Indicate a local master port or remote device access
+ * @destid: Destination ID of the device
+ * @hopcount: Number of switch hops to the device
+ * @from: Offset of current Extended Feature block header (if 0 starts
+ * from ExtFeaturePtr)
+ */
+u32
+rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
+ u8 hopcount, u32 from)
+{
+ u32 reg_val;
+
+ if (from == 0) {
+ if (local)
+ rio_local_read_config_32(port, RIO_ASM_INFO_CAR,
+ ®_val);
+ else
+ rio_mport_read_config_32(port, destid, hopcount,
+ RIO_ASM_INFO_CAR, ®_val);
+ return reg_val & RIO_EXT_FTR_PTR_MASK;
+ } else {
+ if (local)
+ rio_local_read_config_32(port, from, ®_val);
+ else
+ rio_mport_read_config_32(port, destid, hopcount,
+ from, ®_val);
+ return RIO_GET_BLOCK_ID(reg_val);
+ }
+}
+
+/**
* rio_mport_get_feature - query for devices' extended features
* @port: Master port to issue transaction
* @local: Indicate a local master port or remote device access
@@ -472,6 +778,7 @@ int rio_std_route_add_entry(struct rio_m
RIO_STD_RTE_CONF_PORT_SEL_CSR,
(u32)route_port);
}
+
udelay(10);
return 0;
}
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/drivers/rapidio/rio.h w33r7b/drivers/rapidio/rio.h
--- w33r7a/drivers/rapidio/rio.h 2010-02-09 15:11:09.150956000 -0500
+++ w33r7b/drivers/rapidio/rio.h 2010-02-11 15:07:47.861045000 -0500
@@ -18,6 +18,10 @@
extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid,
u8 hopcount, int ftr);
+extern u32 rio_mport_get_physefb(struct rio_mport *port, int local,
+ u16 destid, u8 hopcount);
+extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
+ u8 hopcount, u32 from);
extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
extern int rio_enum_mport(struct rio_mport *mport);
extern int rio_disc_mport(struct rio_mport *mport);
@@ -61,3 +65,28 @@ extern struct rio_route_ops __end_rio_ro
#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
+
+/*
+ * RapidIO Error Management
+ */
+extern struct rio_em_ops __start_rio_em_ops[];
+extern struct rio_em_ops __end_rio_em_ops[];
+
+/* Helpers internal to the RIO core code */
+#define DECLARE_RIO_EM_SECTION(section, name, vid, did, init_hook, em_hook) \
+ static const struct rio_em_ops __rio_em_##name __used \
+ __section(section) = { vid, did, init_hook, em_hook };
+
+/**
+ * DECLARE_RIO_EM_OPS - Registers switch EM operations
+ * @vid: RIO vendor ID
+ * @did: RIO device ID
+ * @init_hook: Callback that initializes device specific EM
+ * @em_hook: Callback that handles device specific EM
+ *
+ * A &struct rio_em_ops is initialized with the ops and placed into a
+ * RIO-specific kernel section.
+ */
+#define DECLARE_RIO_EM_OPS(vid, did, init_hook, em_hook) \
+ DECLARE_RIO_EM_SECTION(.rio_em_ops, vid##did, \
+ vid, did, init_hook, em_hook)
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/drivers/rapidio/switches/tsi568.c w33r7b/drivers/rapidio/switches/tsi568.c
--- w33r7a/drivers/rapidio/switches/tsi568.c 2010-02-09 15:11:09.201908000 -0500
+++ w33r7b/drivers/rapidio/switches/tsi568.c 2010-02-11 11:04:15.904955000 -0500
@@ -25,6 +25,9 @@
#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
+#define TSI568_SP_MODE_BC 0x10004
+#define TSI568_SP_MODE_PW_DIS 0x08000000
+
static int
tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 route_port)
@@ -104,3 +107,24 @@ tsi568_route_clr_table(struct rio_mport
}
DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_route_add_entry, tsi568_route_get_entry, tsi568_route_clr_table);
+
+static int
+tsi568_em_init(struct rio_dev *rdev)
+{
+ struct rio_mport *mport = rdev->net->hport;
+ u16 destid = rdev->rswitch->destid;
+ u8 hopcount = rdev->rswitch->hopcount;
+ u32 regval;
+
+ pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount);
+
+ /* Make sure that Port-Writes are disabled (for all ports) */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ TSI568_SP_MODE_BC, ®val);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS);
+
+ return 0;
+}
+
+DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_em_init, NULL);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/drivers/rapidio/switches/tsi57x.c w33r7b/drivers/rapidio/switches/tsi57x.c
--- w33r7a/drivers/rapidio/switches/tsi57x.c 2010-02-09 15:11:09.207894000 -0500
+++ w33r7b/drivers/rapidio/switches/tsi57x.c 2010-02-11 15:17:26.949248000 -0500
@@ -25,6 +25,14 @@
#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
+#define TSI578_SP_MODE(n) (0x11004 + n*0x100)
+#define TSI578_SP_MODE_PW_DIS 0x08000000
+
+#define TSI578_SP_CTL_INDEP(n) (0x13004 + n*0x100)
+#define TSI578_SP_LUT_PEINF(n) (0x13010 + n*0x100)
+#define TSI578_SP_CS_TX(n) (0x13014 + n*0x100)
+#define TSI578_SP_INT_STATUS(n) (0x13018 + n*0x100)
+
static int
tsi57x_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 route_port)
@@ -104,3 +112,148 @@ DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RI
DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
+
+static int
+tsi57x_em_init(struct rio_dev *rdev)
+{
+ struct rio_mport *mport = rdev->net->hport;
+ u16 destid = rdev->rswitch->destid;
+ u8 hopcount = rdev->rswitch->hopcount;
+ u32 regval;
+ int portnum;
+
+ pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount);
+
+ for (portnum = 0; portnum < 16; portnum++) {
+ /* Make sure that Port-Writes are enabled (for all ports) */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ TSI578_SP_MODE(portnum), ®val);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ TSI578_SP_MODE(portnum),
+ regval & ~TSI578_SP_MODE_PW_DIS);
+
+ /* Clear all pending interrupts */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr +
+ RIO_PORT_N_ERR_STS_CSR(portnum),
+ ®val);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr +
+ RIO_PORT_N_ERR_STS_CSR(portnum),
+ regval & 0x07120214);
+
+ rio_mport_read_config_32(mport, destid, hopcount,
+ TSI578_SP_INT_STATUS(portnum), ®val);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ TSI578_SP_INT_STATUS(portnum),
+ regval & 0x000700bd);
+
+ /* Enable all interrupts to allow ports to send a port-write */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ TSI578_SP_CTL_INDEP(portnum), ®val);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ TSI578_SP_CTL_INDEP(portnum),
+ regval | 0x000b0000);
+
+ /* Skip next (odd) port if the current port is in x4 mode */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ ®val);
+ if ((regval & RIO_PORT_N_CTL_PWIDTH) == RIO_PORT_N_CTL_PWIDTH_4)
+ portnum++;
+ }
+
+ return 0;
+}
+
+static int
+tsi57x_em_handler(struct rio_dev *rdev, u8 portnum)
+{
+ struct rio_mport *mport = rdev->net->hport;
+ u16 destid = rdev->rswitch->destid;
+ u8 hopcount = rdev->rswitch->hopcount;
+ u32 intstat, err_status;
+ int sendcount, checkcount;
+ u8 route_port;
+ u32 regval;
+
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
+ &err_status);
+
+ if ((err_status & RIO_PORT_N_ERR_STS_PORT_OK) &&
+ (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES |
+ RIO_PORT_N_ERR_STS_PW_INP_ES))) {
+ /* Remove any queued packets by locking/unlocking port */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ ®val);
+ if (!(regval & RIO_PORT_N_CTL_LOCKOUT)) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ regval | RIO_PORT_N_CTL_LOCKOUT);
+ udelay(50);
+ rio_mport_write_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
+ regval);
+ }
+
+ /* Read from link maintenance response register to clear
+ * valid bit
+ */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(portnum),
+ ®val);
+
+ /* Send a Packet-Not-Accepted/Link-Request-Input-Status control
+ * symbol to recover from IES/OES
+ */
+ sendcount = 3;
+ while (sendcount) {
+ rio_mport_write_config_32(mport, destid, hopcount,
+ TSI578_SP_CS_TX(portnum), 0x40fc8000);
+ checkcount = 3;
+ while (checkcount--) {
+ udelay(50);
+ rio_mport_read_config_32(
+ mport, destid, hopcount,
+ rdev->phys_efptr +
+ RIO_PORT_N_MNT_RSP_CSR(portnum),
+ ®val);
+ if (regval & RIO_PORT_N_MNT_RSP_RVAL)
+ goto exit_es;
+ }
+
+ sendcount--;
+ }
+ }
+
+exit_es:
+ /* Clear implementation specific error status bits */
+ rio_mport_read_config_32(mport, destid, hopcount,
+ TSI578_SP_INT_STATUS(portnum), &intstat);
+ pr_debug("TSI578[%x:%x] SP%d_INT_STATUS=0x%08x\n",
+ destid, hopcount, portnum, intstat);
+
+ if (intstat & 0x10000) {
+ rio_mport_read_config_32(mport, destid, hopcount,
+ TSI578_SP_LUT_PEINF(portnum), ®val);
+ regval = (mport->sys_size) ? (regval >> 16) : (regval >> 24);
+ route_port = rdev->rswitch->route_table[regval];
+ pr_debug("RIO: TSI578[%s] P%d LUT Parity Error (destID=%d)\n",
+ rio_name(rdev), portnum, regval);
+ tsi57x_route_add_entry(mport, destid, hopcount,
+ RIO_GLOBAL_TABLE, regval, route_port);
+ }
+
+ rio_mport_write_config_32(mport, destid, hopcount,
+ TSI578_SP_INT_STATUS(portnum),
+ intstat & 0x000700bd);
+
+ return 0;
+}
+
+DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_em_init, tsi57x_em_handler);
+DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_em_init, tsi57x_em_handler);
+DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_em_init, tsi57x_em_handler);
+DECLARE_RIO_EM_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_em_init, tsi57x_em_handler);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/include/asm-generic/vmlinux.lds.h w33r7b/include/asm-generic/vmlinux.lds.h
--- w33r7a/include/asm-generic/vmlinux.lds.h 2010-02-06 17:17:12.000000000 -0500
+++ w33r7b/include/asm-generic/vmlinux.lds.h 2010-02-10 17:02:30.541567000 -0500
@@ -247,10 +247,13 @@
} \
\
/* RapidIO route ops */ \
- .rio_route : AT(ADDR(.rio_route) - LOAD_OFFSET) { \
+ .rio_ops : AT(ADDR(.rio_ops) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_rio_route_ops) = .; \
*(.rio_route_ops) \
VMLINUX_SYMBOL(__end_rio_route_ops) = .; \
+ VMLINUX_SYMBOL(__start_rio_em_ops) = .; \
+ *(.rio_em_ops) \
+ VMLINUX_SYMBOL(__end_rio_em_ops) = .; \
} \
\
TRACEDATA \
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/include/linux/rio.h w33r7b/include/linux/rio.h
--- w33r7a/include/linux/rio.h 2010-02-09 15:11:09.280832000 -0500
+++ w33r7b/include/linux/rio.h 2010-02-11 13:07:33.147325000 -0500
@@ -64,6 +64,8 @@
#define RIO_INB_MBOX_RESOURCE 1
#define RIO_OUTB_MBOX_RESOURCE 2
+#define RIO_PW_MSG_SIZE 64
+
extern struct bus_type rio_bus_type;
extern struct list_head rio_devices; /* list of all devices */
@@ -107,11 +109,15 @@ struct rio_dev {
u32 swpinfo; /* Only used for switches */
u32 src_ops;
u32 dst_ops;
+ u32 comp_tag;
+ u32 phys_efptr;
+ u32 em_efptr;
u64 dma_mask;
struct rio_switch *rswitch; /* RIO switch info */
struct rio_driver *driver; /* RIO driver claiming this device */
struct device dev; /* LDM device structure */
struct resource riores[RIO_MAX_DEV_RESOURCES];
+ int (*pwcback) (struct rio_dev *rdev, u32* msg, int step);
u16 destid;
};
@@ -211,9 +217,12 @@ struct rio_net {
* @hopcount: Hopcount to this switch
* @destid: Associated destid in the path
* @route_table: Copy of switch routing table
+ * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0
* @add_entry: Callback for switch-specific route add function
* @get_entry: Callback for switch-specific route get function
* @clr_table: Callback for switch-specific clear route table function
+ * @em_init: Callback for switch-specific error management initialization function
+ * @em_handle: Callback for switch-specific error management handler function
*/
struct rio_switch {
struct list_head node;
@@ -221,12 +230,15 @@ struct rio_switch {
u16 hopcount;
u16 destid;
u8 *route_table;
+ u32 port_ok;
int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 route_port);
int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 * route_port);
int (*clr_table) (struct rio_mport *mport, u16 destid, u8 hopcount,
u16 table);
+ int (*em_init) (struct rio_dev *dev);
+ int (*em_handle) (struct rio_dev *dev, u8 swport);
};
/* Low-level architecture-dependent routines */
@@ -238,6 +250,7 @@ struct rio_switch {
* @cread: Callback to perform network read of config space.
* @cwrite: Callback to perform network write of config space.
* @dsend: Callback to send a doorbell message.
+ * @pwenable: Callback to enable/disable port-write message handling.
*/
struct rio_ops {
int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len,
@@ -249,6 +262,7 @@ struct rio_ops {
int (*cwrite) (struct rio_mport *mport, int index, u16 destid,
u8 hopcount, u32 offset, int len, u32 data);
int (*dsend) (struct rio_mport *mport, int index, u16 destid, u16 data);
+ int (*pwenable) (struct rio_mport *mport, int enable);
};
#define RIO_RESOURCE_MEM 0x00000100
@@ -325,6 +339,22 @@ struct rio_route_ops {
u16 table);
};
+/**
+ * struct rio_em_ops - Per-switch error management operations
+ * @vid: RIO vendor ID
+ * @did: RIO device ID
+ * @init_hook: Switch specific error management initialization (may be NULL)
+ * @handler_hook: Switch specific error management handler (may be NULL)
+ *
+ * Defines the operations that are necessary to initialize and handle
+ * error management events for a particular RIO switch device.
+ */
+struct rio_em_ops {
+ u16 vid, did;
+ int (*init_hook) (struct rio_dev *dev);
+ int (*handler_hook) (struct rio_dev *dev, u8 swport);
+};
+
/* Architecture and hardware-specific functions */
extern int rio_init_mports(void);
extern void rio_register_mport(struct rio_mport *);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/include/linux/rio_drv.h w33r7b/include/linux/rio_drv.h
--- w33r7a/include/linux/rio_drv.h 2010-02-06 17:17:12.000000000 -0500
+++ w33r7b/include/linux/rio_drv.h 2010-02-10 17:02:30.630559000 -0500
@@ -413,6 +413,12 @@ void rio_release_regions(struct rio_dev
int rio_request_region(struct rio_dev *, int, char *);
void rio_release_region(struct rio_dev *, int);
+/* Port-Write management */
+extern int rio_request_inb_pwrite(struct rio_dev *,
+ int (*)(struct rio_dev *, u32*, int));
+extern int rio_release_inb_pwrite(struct rio_dev *);
+extern int rio_inb_pwrite_handler(u32 *pw_msg);
+
/* LDM support */
int rio_register_driver(struct rio_driver *);
void rio_unregister_driver(struct rio_driver *);
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/include/linux/rio_regs.h w33r7b/include/linux/rio_regs.h
--- w33r7a/include/linux/rio_regs.h 2010-02-09 15:11:09.318794000 -0500
+++ w33r7b/include/linux/rio_regs.h 2010-02-11 13:11:02.420875000 -0500
@@ -192,10 +192,14 @@
#define RIO_EFB_PAR_EP_ID 0x0001 /* [IV] LP/LVDS EP Devices */
#define RIO_EFB_PAR_EP_REC_ID 0x0002 /* [IV] LP/LVDS EP Recovery Devices */
#define RIO_EFB_PAR_EP_FREE_ID 0x0003 /* [IV] LP/LVDS EP Free Devices */
+#define RIO_EFB_SER_EP_ID_V13P 0x0001 /* [VI] LP/Serial EP Devices, RapidIO Spec ver 1.3 and above */
+#define RIO_EFB_SER_EP_REC_ID_V13P 0x0002 /* [VI] LP/Serial EP Recovery Devices, RapidIO Spec ver 1.3 and above */
+#define RIO_EFB_SER_EP_FREE_ID_V13P 0x0003 /* [VI] LP/Serial EP Free Devices, RapidIO Spec ver 1.3 and above */
#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */
#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */
#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */
#define RIO_EFB_SER_EP_FREC_ID 0x0009 /* [VI] LP/Serial EP Free Recovery Devices */
+#define RIO_EFB_ERR_MGMNT 0x0007 /* [VIII] Error Management Extensions */
/*
* Physical 8/16 LP-LVDS
@@ -211,15 +215,65 @@
#define RIO_PORT_MNT_HEADER 0x0000
#define RIO_PORT_REQ_CTL_CSR 0x0020
#define RIO_PORT_RSP_CTL_CSR 0x0024 /* 0x0001/0x0002 */
+#define RIO_PORT_LINKTO_CTL_CSR 0x0020 /* Serial */
+#define RIO_PORT_RSPTO_CTL_CSR 0x0024 /* Serial */
#define RIO_PORT_GEN_CTL_CSR 0x003c
#define RIO_PORT_GEN_HOST 0x80000000
#define RIO_PORT_GEN_MASTER 0x40000000
#define RIO_PORT_GEN_DISCOVERED 0x20000000
#define RIO_PORT_N_MNT_REQ_CSR(x) (0x0040 + x*0x20) /* 0x0002 */
#define RIO_PORT_N_MNT_RSP_CSR(x) (0x0044 + x*0x20) /* 0x0002 */
+#define RIO_PORT_N_MNT_RSP_RVAL 0x80000000 /* Response Valid */
+#define RIO_PORT_N_MNT_RSP_ASTAT 0x000003e0 /* ackID Status */
+#define RIO_PORT_N_MNT_RSP_LSTAT 0x0000001f /* Link Status */
#define RIO_PORT_N_ACK_STS_CSR(x) (0x0048 + x*0x20) /* 0x0002 */
-#define RIO_PORT_N_ERR_STS_CSR(x) (0x58 + x*0x20)
-#define PORT_N_ERR_STS_PORT_OK 0x00000002
-#define RIO_PORT_N_CTL_CSR(x) (0x5c + x*0x20)
+#define RIO_PORT_N_ACK_CLEAR 0x80000000
+#define RIO_PORT_N_ACK_INBOUND 0x1f000000
+#define RIO_PORT_N_ACK_OUTSTAND 0x00001f00
+#define RIO_PORT_N_ACK_OUTBOUND 0x0000001f
+#define RIO_PORT_N_ERR_STS_CSR(x) (0x0058 + x*0x20)
+#define RIO_PORT_N_ERR_STS_PW_OUT_ES 0x00010000 /* Output Error-stopped */
+#define RIO_PORT_N_ERR_STS_PW_INP_ES 0x00000100 /* Input Error-stopped */
+#define RIO_PORT_N_ERR_STS_PW_PEND 0x00000010 /* Port-Write Pending */
+#define RIO_PORT_N_ERR_STS_PORT_ERR 0x00000004
+#define RIO_PORT_N_ERR_STS_PORT_OK 0x00000002
+#define RIO_PORT_N_ERR_STS_PORT_UNINIT 0x00000001
+#define RIO_PORT_N_CTL_CSR(x) (0x005c + x*0x20)
+#define RIO_PORT_N_CTL_PWIDTH 0xc0000000
+#define RIO_PORT_N_CTL_PWIDTH_1 0x00000000
+#define RIO_PORT_N_CTL_PWIDTH_4 0x40000000
+#define RIO_PORT_N_CTL_LOCKOUT 0x00000002
+
+/*
+ * Error Management Extensions (RapidIO 1.3+, Part 8)
+ *
+ * Extended Features Block ID=0x0007
+ */
+
+/* General EM Registers (Common for all Ports) */
+
+#define RIO_EM_EFB_HEADER 0x000 /* Error Management Extensions Block Header */
+#define RIO_EM_LTL_ERR_DETECT 0x008 /* Logical/Transport Layer Error Detect CSR */
+#define RIO_EM_LTL_ERR_EN 0x00c /* Logical/Transport Layer Error Enable CSR */
+#define RIO_EM_LTL_HIADDR_CAP 0x010 /* Logical/Transport Layer High Address Capture CSR */
+#define RIO_EM_LTL_ADDR_CAP 0x014 /* Logical/Transport Layer Address Capture CSR */
+#define RIO_EM_LTL_DEVID_CAP 0x018 /* Logical/Transport Layer Device ID Capture CSR */
+#define RIO_EM_LTL_CTRL_CAP 0x01c /* Logical/Transport Layer Control Capture CSR */
+#define RIO_EM_PW_TGT_DEVID 0x028 /* Port-write Target deviceID CSR */
+#define RIO_EM_PKT_TTL 0x02c /* Packet Time-to-live CSR */
+
+/* Per-Port EM Registers */
+
+#define RIO_EM_PN_ERR_DETECT(x) (0x040 + x*0x40) /* Port N Error Detect CSR */
+#define REM_PED_IMPL_SPEC 0x80000000
+#define REM_PED_LINK_TO 0x00000001
+#define RIO_EM_PN_ERRRATE_EN(x) (0x044 + x*0x40) /* Port N Error Rate Enable CSR */
+#define RIO_EM_PN_ATTRIB_CAP(x) (0x048 + x*0x40) /* Port N Attributes Capture CSR */
+#define RIO_EM_PN_PKT_CAP_0(x) (0x04c + x*0x40) /* Port N Packet/Control Symbol Capture 0 CSR */
+#define RIO_EM_PN_PKT_CAP_1(x) (0x050 + x*0x40) /* Port N Packet Capture 1 CSR */
+#define RIO_EM_PN_PKT_CAP_2(x) (0x054 + x*0x40) /* Port N Packet Capture 2 CSR */
+#define RIO_EM_PN_PKT_CAP_3(x) (0x058 + x*0x40) /* Port N Packet Capture 3 CSR */
+#define RIO_EM_PN_ERRRATE(x) (0x068 + x*0x40) /* Port N Error Rate CSR */
+#define RIO_EM_PN_ERRRATE_TR(x) (0x06c + x*0x40) /* Port N Error Rate Threshold CSR */
#endif /* LINUX_RIO_REGS_H */
---
Important Notice: This message is intended for the use of the individual to whom it is addressed and may contain information which is privileged, confidential and/or exempt from disclosure under applicable law. If the reader of this message is not the intended recipient, or is not the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender immediately by telephone or return e-mail and delete the original message from your systems. Thank you.
^ permalink raw reply
* Re: Please pull mpc5xxx support for -next
From: Grant Likely @ 2010-02-24 15:21 UTC (permalink / raw)
To: Benjamin Herrenschmidt, linuxppc-dev; +Cc: Ernst Schwab, Anatolij Gustschin
In-Reply-To: <fa686aa41002172237l1d3976avc7f88fd38755ca5e@mail.gmail.com>
Hi Ben,
Just sending a reminder on this pull request. I haven't seen these
commits show up in your -next branch yet.
Thanks,
g.
On Wed, Feb 17, 2010 at 11:37 PM, Grant Likely
<grant.likely@secretlab.ca> wrote:
> Hi Ben,
>
> Here's all the stuff I've got queued up for 2.6.34. =A0Mostly mpc5121
> support, but some 5200 stuff too. =A0These commits have already had some
> time in linux-next.
>
> Cheers,
> g.
>
> The following changes since commit 724e6d3fe8003c3f60bf404bf22e4e331327c5=
96:
> =A0Linus Torvalds (1):
> =A0 =A0 =A0 =A0Linux 2.6.33-rc8
>
> are available in the git repository at:
>
> =A0git://git.secretlab.ca/git/linux-2.6.git next
>
> Anatolij Gustschin (10):
> =A0 =A0 =A0powerpc/mpc5121: avoid using arch_initcall for clock init
> =A0 =A0 =A0powerpc/mpc5121: Add machine restart support
> =A0 =A0 =A0rtc: Add MPC5121 Real time clock driver
> =A0 =A0 =A0powerpc/mpc5121: create and register NFC device
> =A0 =A0 =A0powerpc/mpc5121: update mpc5121ads DTS
> =A0 =A0 =A0powerpc/mpc5121: Add default config for MPC5121
> =A0 =A0 =A0serial: mpc52xx_uart: re-enable mpc5121 PSC UART support
> =A0 =A0 =A0powerpc: doc/dts-bindings: document mpc5121 psc uart dts-bindi=
ngs
> =A0 =A0 =A0powerpc/mpc5121: enable support for more PSC UARTs
> =A0 =A0 =A0powerpc/mpc5121: correct DIU compatible property
>
> Ernst Schwab (1):
> =A0 =A0 =A0powerpc/of: added documentation for spi chipselects
>
> =A0.../powerpc/dts-bindings/fsl/mpc5121-psc.txt =A0 =A0 =A0 | =A0 70 +
> =A0Documentation/powerpc/dts-bindings/fsl/spi.txt =A0 =A0 | =A0 =A07 +
> =A0arch/powerpc/boot/dts/mpc5121ads.dts =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0=
55 +-
> =A0arch/powerpc/configs/mpc512x_defconfig =A0 =A0 =A0 =A0 =A0 =A0 | 1694 =
++++++++++++++++++++
> =A0arch/powerpc/include/asm/mpc5121.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =
=A0 24 +
> =A0arch/powerpc/include/asm/mpc52xx_psc.h =A0 =A0 =A0 =A0 =A0 =A0 | =A0 =
=A04 +
> =A0arch/powerpc/platforms/512x/clock.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 =A06 +-
> =A0arch/powerpc/platforms/512x/mpc5121_ads.c =A0 =A0 =A0 =A0 =A0| =A0 =A0=
3 +-
> =A0arch/powerpc/platforms/512x/mpc5121_generic.c =A0 =A0 =A0| =A0 =A03 +-
> =A0arch/powerpc/platforms/512x/mpc512x.h =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0=
=A03 +
> =A0arch/powerpc/platforms/512x/mpc512x_shared.c =A0 =A0 =A0 | =A0 43 +
> =A0drivers/rtc/Kconfig =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0| =A0 10 +
> =A0drivers/rtc/Makefile =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 | =A0 =A01 +
> =A0drivers/rtc/rtc-mpc5121.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0| =A0387 +++++
> =A0drivers/serial/mpc52xx_uart.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0| =A0251 +++-
> =A0drivers/video/fsl-diu-fb.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 | =A0 =A05 +
> =A016 files changed, 2522 insertions(+), 44 deletions(-)
> =A0create mode 100644 Documentation/powerpc/dts-bindings/fsl/mpc5121-psc.=
txt
> =A0create mode 100644 arch/powerpc/configs/mpc512x_defconfig
> =A0create mode 100644 arch/powerpc/include/asm/mpc5121.h
> =A0create mode 100644 drivers/rtc/rtc-mpc5121.c
>
>
> --
> Grant Likely, B.Sc., P.Eng.
> Secret Lab Technologies Ltd.
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH 2/7] RapidIO: Add switch locking during discovery
From: Alexandre Bounine @ 2010-02-24 15:20 UTC (permalink / raw)
To: mporter; +Cc: abounine, linuxppc-dev, linux-kernel, thomas.moll.ext,
thomas.moll
From: Alexandre Bounine <alexandre.bounine@idt.com>
Add switch access locking during RapidIO discovery. Access lock is
required when reading switch routing table contents due to indexed mechanism
of RT addressing.
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Tested-by: Thomas Moll <thomas.moll@sysgo.com>
---
rio-scan.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 79 insertions(+), 9 deletions(-)
diff -x '*.pj' -X dontdiff_2.6.32-rc5 -pNur w33r7a/drivers/rapidio/rio-scan.c w33r7b/drivers/rapidio/rio-scan.c
--- w33r7a/drivers/rapidio/rio-scan.c 2010-02-09 15:11:09.141972000 -0500
+++ w33r7b/drivers/rapidio/rio-scan.c 2010-02-10 16:13:56.382802000 -0500
@@ -750,6 +750,7 @@ rio_disc_peer(struct rio_net *net, struc
int num_ports;
struct rio_dev *rdev;
u16 ndestid;
+ u32 result;
/* Setup new RIO device */
if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) {
@@ -778,6 +779,27 @@ rio_disc_peer(struct rio_net *net, struc
pr_debug(
"RIO: scanning device on port %d\n",
port_num);
+
+ /* Attempt to acquire device lock */
+ rio_mport_write_config_32(port, destid,
+ hopcount,
+ RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ rio_mport_read_config_32(port, destid, hopcount,
+ RIO_HOST_DID_LOCK_CSR, &result);
+ while (result != port->host_deviceid) {
+ /* Delay a bit */
+ mdelay(1);
+ /* Try to acquire device lock again */
+ rio_mport_write_config_32(port, destid,
+ hopcount,
+ RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ rio_mport_read_config_32(port, destid,
+ hopcount,
+ RIO_HOST_DID_LOCK_CSR, &result);
+ }
+
for (ndestid = 0;
ndestid < RIO_ANY_DESTID(port->sys_size);
ndestid++) {
@@ -789,6 +811,19 @@ rio_disc_peer(struct rio_net *net, struc
break;
}
+ /* Release device lock */
+ rio_mport_write_config_32(port, destid,
+ hopcount,
+ RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ rio_mport_read_config_32(port, destid, hopcount,
+ RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) != 0xffff) {
+ pr_info("RIO: badness when releasing " \
+ "host lock on %s\n",
+ rio_name(rdev));
+ }
+
if (rio_disc_peer
(net, port, ndestid, hopcount + 1) < 0)
return -1;
@@ -958,17 +993,45 @@ static void rio_build_route_tables(void)
struct rio_dev *rdev;
int i;
u8 sport;
+ u32 result;
list_for_each_entry(rdev, &rio_devices, global_list)
- if (rio_is_switch(rdev))
- for (i = 0;
- i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
- i++) {
- if (rio_route_get_entry
- (rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE,
- i, &sport) < 0)
- continue;
- rdev->rswitch->route_table[i] = sport;
+ if (rio_is_switch(rdev)) {
+ /* Attempt to acquire device lock */
+ rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
+ rdev->net->hport->host_deviceid);
+ rio_read_config_32(rdev,
+ RIO_HOST_DID_LOCK_CSR, &result);
+ while (result != rdev->net->hport->host_deviceid) {
+ /* Delay a bit */
+ mdelay(1);
+ /* Attempt to acquire device lock again */
+ rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
+ rdev->net->hport->host_deviceid);
+ rio_read_config_32(rdev,
+ RIO_HOST_DID_LOCK_CSR, &result);
+ }
+
+ for (i = 0;
+ i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
+ i++) {
+ if (rio_route_get_entry
+ (rdev->net->hport, rdev->rswitch,
+ RIO_GLOBAL_TABLE, i, &sport) < 0)
+ continue;
+ rdev->rswitch->route_table[i] = sport;
+ }
+
+ /* Release device lock */
+ rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
+ rdev->net->hport->host_deviceid);
+ rio_read_config_32(rdev,
+ RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) != 0xffff) {
+ pr_info("RIO: badness when releasing " \
+ "host lock on %s\n", rio_name(rdev));
+ }
+
}
}
@@ -1027,6 +1090,13 @@ int __devinit rio_disc_mport(struct rio_
del_timer_sync(&rio_enum_timer);
pr_debug("done\n");
+
+ /* Read DestID assigned by enumerator */
+ rio_local_read_config_32(mport, RIO_DID_CSR,
+ &mport->host_deviceid);
+ mport->host_deviceid = RIO_GET_DID(mport->sys_size,
+ mport->host_deviceid);
+
if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size),
0) < 0) {
printk(KERN_INFO
---
Important Notice: This message is intended for the use of the individual to whom it is addressed and may contain information which is privileged, confidential and/or exempt from disclosure under applicable law. If the reader of this message is not the intended recipient, or is not the employee or agent responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender immediately by telephone or return e-mail and delete the original message from your systems. Thank you.
^ permalink raw reply
* Re: [PATCH] Fixed statement without effect by using a correct empty instruction
From: Marcus Meissner @ 2010-02-24 13:43 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, albrecht.dress
In-Reply-To: <fa686aa41002240540s2044ecaaj3ce04021719a51ef@mail.gmail.com>
On Wed, Feb 24, 2010 at 06:40:37AM -0700, Grant Likely wrote:
> On Wed, Feb 24, 2010 at 1:51 AM, Marcus Meissner <meissner@suse.de> wrote:
> > This fixes this build failure:
> > cc1: warnings being treated as errors
> > /usr/src/packages/BUILD/kernel-default-2.6.33/linux-2.6.32/arch/powerpc/platforms/52xx/mpc52xx_gpt.c: In function 'mpc52xx_gpt_probe':
> > /usr/src/packages/BUILD/kernel-default-2.6.33/linux-2.6.32/arch/powerpc/platforms/52xx/mpc52xx_gpt.c:761:3: error: statement with no effect
> >
> > Signed-off-by: Marcus Meissner <meissner@suse.de>
>
> Hi Marcus, thanks for the patch. One comment below...
>
> > ---
> > arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 2 +-
> > 1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> > index 6f8ebe1..88231d8 100644
> > --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> > +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> > @@ -711,7 +711,7 @@ static int __devinit mpc52xx_gpt_wdt_init(void)
> > return 0;
> > }
> >
> > -#define mpc52xx_gpt_wdt_setup(x, y) (0)
> > +#define mpc52xx_gpt_wdt_setup(x, y) do { } while (0)
>
> As Andrew likes to say, we should be programming in C instead of preprocessor.
>
> -#define mpc52xx_gpt_wdt_setup(x, y) (0)
> +static inline void mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv
> *gpt, const u32 *period) { }
Sounds good to me too. :)
Ciao, Marcus
^ permalink raw reply
* Re: [PATCH] Fixed statement without effect by using a correct empty instruction
From: Grant Likely @ 2010-02-24 13:40 UTC (permalink / raw)
To: Marcus Meissner; +Cc: linuxppc-dev, albrecht.dress
In-Reply-To: <20100224085137.GA25801@suse.de>
On Wed, Feb 24, 2010 at 1:51 AM, Marcus Meissner <meissner@suse.de> wrote:
> This fixes this build failure:
> cc1: warnings being treated as errors
> /usr/src/packages/BUILD/kernel-default-2.6.33/linux-2.6.32/arch/powerpc/p=
latforms/52xx/mpc52xx_gpt.c: In function 'mpc52xx_gpt_probe':
> /usr/src/packages/BUILD/kernel-default-2.6.33/linux-2.6.32/arch/powerpc/p=
latforms/52xx/mpc52xx_gpt.c:761:3: error: statement with no effect
>
> Signed-off-by: Marcus Meissner <meissner@suse.de>
Hi Marcus, thanks for the patch. One comment below...
> ---
> =A0arch/powerpc/platforms/52xx/mpc52xx_gpt.c | =A0 =A02 +-
> =A01 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/pla=
tforms/52xx/mpc52xx_gpt.c
> index 6f8ebe1..88231d8 100644
> --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
> @@ -711,7 +711,7 @@ static int __devinit mpc52xx_gpt_wdt_init(void)
> =A0 =A0 =A0 =A0return 0;
> =A0}
>
> -#define mpc52xx_gpt_wdt_setup(x, y) =A0 =A0 =A0 =A0 =A0 =A0(0)
> +#define mpc52xx_gpt_wdt_setup(x, y) =A0 =A0 =A0 =A0 =A0 =A0do { } while =
(0)
As Andrew likes to say, we should be programming in C instead of preprocess=
or.
-#define mpc52xx_gpt_wdt_setup(x, y) (0)
+static inline void mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv
*gpt, const u32 *period) { }
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox