LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-11 17:02 UTC (permalink / raw)
  To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101011105031.52a5c06a@udp111988uds.am.freescale.net>

Re-ordering your questions a bit:

> What board are you using?  What kernel?

One of 2 boards: Either an Embedded Planet or a Performance Tech uTCA
board based on the MPC8641D, running the 2.6.26 as supplied by EP.


> On Sat, 9 Oct 2010 10:52:49 -0500
> Documentation/powerpc/dts-bindings/fsl/mpic.txt
Not present in the version I have.

>
> Plus the chip manual, for the register offsets.
I have that now, so at least one part of the fog is a bit less dense.

> If it's not in the dts, add it.  If for whatever reason that's not an
> option, you can use irq_create_mapping() as I mentioned in the previous
> e-mail.
And as I've said previously, I have no good info on HOW to add the nodes,
WHAT to add, or WHERE. You may as well be saying "Bargle the Narbog".

And when I try to use irq_create_mapping() it seg faults, which doesn't
exactly help me get my interrupt hooked up.

(crotchety old man mode)Kids these day - when I was a kid, you just
grabbed the IRQ vector into your assembly code and away you went. Now GET
OFF MY YARD!(/crotchety old man mode).

> If you grep arch/powerpc/boot/dts for msi in a reasonably recent kernel
> you should find msi nodes.

ddhagood@WIC-102362:..Workspace/Linux_Kernel_for_PPC> grep msi
arch/powerpc/boot/dts  -ir
arch/powerpc/boot/dts/glacier.dts:			enable-msi-hole;
arch/powerpc/boot/dts/taishan.dts:			enable-msi-hole;
arch/powerpc/boot/dts/canyonlands.dts:			enable-msi-hole;
arch/powerpc/boot/dts/katmai.dts:			enable-msi-hole;

> What did I get signed up for? :-)

It sounds like Tiejun thinks you might be working on, well, basically what
I am working on - a generic interface to allow user space to support being
a endpoint, with the ability to generate interrupts to the host root
complex, get interrupts from the host root complex, provide memory to be
accessed by the host root complex via the PPC's BARs, and to access the
host root complex's PCI address space via the OATMU windows. Something to
allow a person to use a PPC SOC as an endpoint, and to get on with the job
of providing functionality rather than having to deal with esoterica.

I'm hoping to make an interface generic enough to support not only the
PPC, but other devices as well (things I cannot go into due to NDAs at
this time). As a systems programmer, I am tired of re-inventing the wheel
when dealing with being an endpoint - I want to invent the wheel, and push
it uphill to the greater Linux community so that a) others are spared the
pain I am suffering, and b) maybe other SOC vendors will implement my
interface (and thus I won't have to).

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: Scott Wood @ 2010-10-11 15:50 UTC (permalink / raw)
  To: david.hagood; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <adaf806ee1c11621dbb51246bef0acd8.squirrel@localhost>

On Sat, 9 Oct 2010 10:52:49 -0500
<david.hagood@gmail.com> wrote:

> First of all - where is all of this documented? There seems to be a great
> deal of "oral tradition" type knowledge here, but is any of it actually
> written down somewhere? (see below for examples)

Documentation/powerpc/dts-bindings/fsl/mpic.txt

Plus the chip manual, for the register offsets.

> > On Thu, 7 Oct 2010 15:12:26 -0500
> > This is asking for the 256th specifier in the interrupts property in
> > the mpic node -- not what you want.
> 
> That was from some of the previous emails in this thread.
> 
> > Ideally you would have a node for your device with an interrupt
> > specifier that you could look up with irq_of_parse_and_map().
> 
> OK, and how do these devices come into being? From what I can tell, they
> are defined by uBoot, and if uBoot doesn't define it, then you are out of
> luck.

More commonly they're statically defined in the dts file, not
dynamically created by u-boot.

If it's not in the dts, add it.  If for whatever reason that's not an
option, you can use irq_create_mapping() as I mentioned in the previous
e-mail.

> * A set of APIs (irq_of_parse_and_map(), irq_create_mapping) that were,
> for all intents, undocumented (just "here's the parameters", no
> description of when and how to use them), that took a ???? and returned a
> ???? (because, with the documentation I had, that's basically all I could
> say about them).

Yes, there are many parts of the kernel that could use better
documentation.

> > BTW, the MSIs are already described in an msi node in the device tree.
> 
> As I stated previously - not that I can see.

What board are you using?  What kernel?

If you grep arch/powerpc/boot/dts for msi in a reasonably recent kernel
you should find msi nodes.

> It may be they are defined in PCI Root Complex mode, 

No, it's a separate node.

-Scott

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: Scott Wood @ 2010-10-11 15:51 UTC (permalink / raw)
  To: tiejun.chen; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DE2B.7040504@windriver.com>

On Mon, 11 Oct 2010 17:51:39 +0800
"tiejun.chen" <tiejun.chen@windriver.com> wrote:

> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
> previously said. And sounds Scott will do something to support EP for Freescale
> chip.

What did I get signed up for? :-)

-Scott

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-11 14:44 UTC (permalink / raw)
  To: tiejun.chen; +Cc: Scott Wood, david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DE2B.7040504@windriver.com>


> You should define MSI device nodes on your target dts. And you can refer
> to the
> file, mpc8572ds.dts.

I see nothing in that file that defines any MSIs. I see code that looks
like it maps ROOT COMPLEX MODE interrupts on regular PCI interfaces, which
IS NOT WHAT I AM DOING.

Since it seems I have been unclear, let me state this as clearly as possible.

I AM DOING ENDPOINT MODE.


> I think you can check fsl_msi.c to figure out what you want.
Except that file doesn't exist in the 2.6.26 kernel with which I am working.

> Firstly you should use irq_of_parse_and_map()/irq_create_mapping() to map
> the
> real hardware irq to virtual irq. Then use request_irq() with the virtual
> irq to
> hook your interrupt handler.

Except I have no device to pass irq_of_parse_and_map, and when I call
irq_create_mapping it seg faults.

>
> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support
> EP as I
> previously said.

It only "supports" EP mode in the sense that it sets the hardware up to
export a BAR, and does nothing else. It doesn't provide any means for any
other code to actually DO anything in that mode. It doesn't define a way
to be interrupted by the root complex, nor to do anything when that
interrupt happens. It doesn't supply any meaningful framework to get any
data from the Root Complex.

That's the whole reason I am trying to make a piece of code that actually
WILL make those things available in a useful fashion.

^ permalink raw reply

* Re: powerpc, fs_enet: scanning PHY after Linux is up
From: Holger brunck @ 2010-10-11 11:49 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, devicetree-discuss, hs, Detlev Zundel, netdev
In-Reply-To: <20101008170615.GC3863@angua.secretlab.ca>

Hi Grant,

On 10/08/2010 07:06 PM, Grant Likely wrote:
> On Fri, Oct 08, 2010 at 10:50:50AM +0200, Holger brunck wrote:
>>> On Wed, Oct 6, 2010 at 3:53 AM, Heiko Schocher <hs@denx.de> wrote:
>>
>>>> Wouldn;t it be good, just if we need a PHY (on calling fs_enet_open)
>>>> to look if there is one?
>>>>
>>>> Something like that (not tested):
>>>>
>>>> in drivers/net/fs_enet/fs_enet-main.c in fs_init_phy()
>>>> called from fs_enet_open():
>>>>
>>>> Do first:
>>>> phydev =  of_phy_find_device(fep->fpi->phy_node);
>>>>
>>>> Look if there is a driver (phy_dev->drv == NULL ?)
>>>>
>>>> If not, call new function
>>>> of_mdiobus_register_phy(mii_bus, fep->fpi->phy_node)
>>>> see below patch for it.
>>>>
>>>> If this succeeds, all is OK, and we can use this phy,
>>>> else ethernet not work.
>>>
>>> I don't like this approach because it muddies the concept of which
>>> device is actually responsible for managing the phys on the bus.  Is
>>> it managed by the mdio bus device or the Ethernet device?  It also has
>>> a potential race condition.  Whereas triggering a late driver bind
>>> will be safe.
>>>
>>> Alternately, I'd also be okay with a common method to trigger a
>>> reprobe of a particular phy from userspace, but I fear that would be a
>>> significantly more complex solution.
>>>
>>>>
>>>> !!just no idea, how to get mii_bus pointer ...
>>>
>>> You'd have to get the parent of the phy node, and then loop over all
>>> the registered mdio busses looking for a bus that uses that node.
>>>
>>
>> you say that you don't like the approach to probe the phy again in fs_enet_open,
>> but currently I don't understand what would be the alternate trigger point to
>> rescan the mdio bus?
> 
> Same trigger point, but different operation.  At fs_enet_open time,
> instead of registering the phy_device, the phy layer could sanity
> check the already registered phy_device, and refuse to connect to it
> if the phy isn't responding.  If it is responding, then it could
> re-attempt binding a phy_driver to it (although I just realized that
> this has other problems, such as correct module loading.  See below)
> 

ok.

>> I made a first patch to enhance the phy_device structure and rescan the mdio bus
>> at time of fs_enet_open (because I didn't see a better trigger point). The
>> advantage is that we got the mii_bus pointer and the phy addr stored in the
>> already created phy device structure and is therefore easy to use. See the patch
>> below for this modifications. Whats currently missing in the patch is to set the
>> phy_id if the phy was scanned later after phy_device creation. For the mgcoge
>> board it seems to solve our problem, but maybe I miss something important.
>>
>> Best regards
>> Holger Brunck
>>
>> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
>> index ec2f503..6bc117f 100644
>> --- a/drivers/net/fs_enet/fs_enet-main.c
>> +++ b/drivers/net/fs_enet/fs_enet-main.c
>> @@ -775,7 +774,8 @@ static int fs_enet_open(struct net_device *dev)
>>  {
>>         struct fs_enet_private *fep = netdev_priv(dev);
>>         int r;
>> -       int err;
>> +       int err = 0;
>> +       u32 phy_id = 0;
>>
>>         /* to initialize the fep->cur_rx,... */
>>         /* not doing this, will cause a crash in fs_enet_rx_napi */
>> @@ -795,13 +795,23 @@ static int fs_enet_open(struct net_device *dev)
>>                 return -EINVAL;
>>         }
>>
>> -       err = fs_init_phy(dev);
>> -       if (err) {
>> +       if (fep->phydev == NULL)
>> +               err = fs_init_phy(dev);
>> +
>> +       if (!err && (fep->phydev->available == false))
>> +               r = get_phy_id(fep->phydev->bus, fep->phydev->addr, &phy_id);
>> +
>> +       if (err || (phy_id == 0xffffffff)) {
>>                 free_irq(fep->interrupt, dev);
>>                 if (fep->fpi->use_napi)
>>                         napi_disable(&fep->napi);
>> -               return err;
>> +               if (err)
>> +                       return err;
>> +               else
>> +                       return -EINVAL;
>>         }
>> +       else
>> +               fep->phydev->available = true;
>>         phy_start(fep->phydev);
>>
>>         netif_start_queue(dev);
>> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
>> index adbc0fd..1f443cb 100644
>> --- a/drivers/net/phy/phy_device.c
>> +++ b/drivers/net/phy/phy_device.c
>> @@ -173,6 +173,10 @@ struct phy_device* phy_device_create(struct mii_bus *bus,
>> int addr, int phy_id)
>>         dev->dev.bus = &mdio_bus_type;
>>         dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
>>         dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
>> +       if (phy_id == 0xffffffff)
>> +               dev->available = false;
>> +       else
>> +               dev->available = true;
> 
> This flag shouldn't be necessary.  Just check whether or not
> phy_device->phy_id is sane at phy_attach_direct() time.  If it is
> mostly f's, then don't attach.
>

Yes, indeed it is unneeded. Thanks for pointing out.

>>
>>         dev->state = PHY_DOWN;
>>
>> @@ -232,13 +236,11 @@ struct phy_device * get_phy_device(struct mii_bus *bus,
>> int addr)
>>         int r;
>>
>>         r = get_phy_id(bus, addr, &phy_id);
>> -       if (r)
>> -               return ERR_PTR(r);
>>
>>         /* If the phy_id is mostly Fs, there is no device there */
>> -       if ((phy_id & 0x1fffffff) == 0x1fffffff)
>> -               return NULL;
>> -
>> +       if (((phy_id & 0x1fffffff) == 0x1fffffff) || r)
>> +               phy_id = 0xffffffff;
>> +       /* create phy even if the phy is currently not available */
>>         dev = phy_device_create(bus, addr, phy_id);
> 
> Cannot do it this way because many phylib users probe the bus for phys
> instead of the explicit creation used with the device tree.  There
> needs to be a method to explicitly skip this test when creating a phy;
> possibly by having the device tree code call phy_device_create()
> directly.
> 

Ah ok, every phy_device_create() call from of_mdiobus_register should skip this
test, because if a phy is described in the dts it is present (sooner or later)
and if phy_device_create is called from somewhere else I do this test as usual.
I adapted my patch accordingly.

> Hmmm.... I see another problem.  Deferred probing of the phy will
> potentially cause problems with module loading.  If the binding is
> deferred to phy connect time; then the phy driver may not have time to
> get loaded before the phy layer decides there is no driver and binds
> it to the generic one.  Blech.
> 
> Okay, so it seems like a method of explicitly triggering a phy_device
> rebind from userspace is necessary.  This could be done with a
> per-phy_device sysfs file I suppose.  Just an empty file that when
> read triggers a re-read of the phy id registers, and retries binding a
> driver, including the request_module call in phy_device_create().
> 

Okay I suspected that there is not an easy solution for our problem. Another
solution comes in my mind. If we defer the call to fs_enet_probe at startup. So
enhance the dts entry with something like an hotplug indication and then trigger
via an sysfs entry the call to fs_enet_probe if the phy is up... Other hotplug
devices should have similar problems...

However for our mgcoge board we can live with the fact that we can't load/unload
the driver dynamically. So I think we will go with this modified "out of tree"
patch for our board. Thanks for your support.

Best regards
Holger Brunck

^ permalink raw reply

* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Benjamin Herrenschmidt @ 2010-10-11 11:32 UTC (permalink / raw)
  To: Eran Liberty; +Cc: linux-pci, linuxppc-dev
In-Reply-To: <4CB2E517.8020401@extricom.com>


> BUT if we take into consideration that:
> 1. Freescale is a serious dude in the hood and on the whole does a good 
> job with its products and their Linux support.

Sure but that's irrelevant to the technical problem at hand :-)

> 2. The P2020 does state it has an MSI mechanism support (although one is 
> not present as a PCIe capability header for some reason)

Then it's broken :-(

> 3. Errors in general and AER are major features in PCIe.
> 4. PCIe has been here quite a while and it is not new to Freescale or 
> anyone else.

Right but we don't do AER on ppc44x either, I know we should but for
some reason, AER hasn't been on anybody #1 priority list in embedded
world so far...

> I am much more inclined to believe that I have missed something by a 
> mile then that Freescale did. I just don't know what I am missing.

No, I think you haven't and we just need to fix it :-)

Cheers,
Ben.

> My device tree is a clone of "arch/ powerpc/ boot/ dts/ p2020rdb.dts"
> 
> It has a PCI node that looks like this:
> ----------------------------- snip -----------------------------
>     pci0: pcie@ffe09000 {
>         cell-index = <1>;
>         compatible = "fsl,mpc8548-pcie";
>         device_type = "pci";
>         #interrupt-cells = <1>;
>         #size-cells = <2>;
>         #address-cells = <3>;
>         reg = <0 0xffe09000 0 0x1000>;
>         bus-range = <0 255>;
>         ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
>               0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
>         clock-frequency = <33333333>;
>         interrupt-parent = <&mpic>;
>         interrupts = <25 2>;
>         interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
>         interrupt-map = <
>             /* IDSEL 0x0 */
>             0000 0x0 0x0 0x1 &mpic 0x4 0x1
>             0000 0x0 0x0 0x2 &mpic 0x5 0x1
>             0000 0x0 0x0 0x3 &mpic 0x6 0x1
>             0000 0x0 0x0 0x4 &mpic 0x7 0x1
>             >;
>         pcie@0 {
>             reg = <0x0 0x0 0x0 0x0 0x0>;
>             #size-cells = <2>;
>             #address-cells = <3>;
>             device_type = "pci";
>             ranges = <0x2000000 0x0 0xa0000000
>                   0x2000000 0x0 0xa0000000
>                   0x0 0x20000000
> 
>                   0x1000000 0x0 0x0
>                   0x1000000 0x0 0x0
>                   0x0 0x100000>;
>         };
>     };
> ----------------------------- snap -----------------------------
> 
> and under "soc" it has an MSI node that looks like that:
> ----------------------------- snip -----------------------------
>         msi@41600 {
>             compatible = "fsl,p2020-msi", "fsl,mpic-msi";
>             reg = <0x41600 0x80>;
>             msi-available-ranges = <0 0x100>;
>             interrupts = <
>                 0xe0 0
>                 0xe1 0
>                 0xe2 0
>                 0xe3 0
>                 0xe4 0
>                 0xe5 0
>                 0xe6 0
>                 0xe7 0>;
>             interrupt-parent = <&mpic>;
>         };
> ----------------------------- snap -----------------------------
> 
> -- Liberty
> 

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: David Hagood @ 2010-10-11 11:30 UTC (permalink / raw)
  To: tiejun.chen; +Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DE2B.7040504@windriver.com>

On Mon, 2010-10-11 at 17:51 +0800, tiejun.chen wrote:
> 
> You should define MSI device nodes on your target dts. And you can refer to the
> file, mpc8572ds.dts.
> 
> Often U-Boot dose not generate MSI information and embed that to dtb.
> 
> > 
> > But even assuming you can define these nodes at run time, as far as I can
> > see, you are right back to the question of "and how do I know what the
> > mappings are so I can create the node?" You haven't answered the question,
> > you've just moved where you are asking it.
> 
> I think you can check fsl_msi.c to figure out what you want.
<snip>

> Often most latest classic books/articles always use x86 code as an
example to
> clarify Linux. So you have to understand something on PPC via codes.
But I think
> you will benefit more information from the codes than documents :)
> 

RTFS. That wouldn't be bad advice, if the source were actually
commented. None of these APIS have any meaningful comments in them,
around them, or anywhere near them. You'd think we were back in the old
BASIC days, when comments occupied run-time memory. Code can tell me
WHAT is being done, but not WHY, and not what assumptions are being
made.

So when you say "You should define MSI device nodes on your target dts."
we go right back to my comment of "You haven't answered the question,
you've just moved where you are asking it."

> 
> Firstly you should use irq_of_parse_and_map()/irq_create_mapping() to map the
> real hardware irq to virtual irq. Then use request_irq() with the virtual irq to
> hook your interrupt handler.
And when I do that, I get a segfault as my follow-on mail reports.

> 
> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
> previously said. And sounds Scott will do something to support EP for Freescale
> chip.
I will look at that file.

> 
> Looks you want to your host root complex to trigger MSI to mpc8641 EP target? If
> so I'm a bit confused since MSIs should be delivered to to the Root Complex
> resided on your host.
I want the host to be able to interrupt the PPC. Since this is PCIe, the
only way that will be working is for the root complex to do a write to
somewhere on the PPC. This is basically the same mechanism as MSI, only
with the PPC as the target of the write rather than the root complex.
Obviously, the rest of the PCI devices will be sending interrupts to the
root complex, some via MSI. That has nothing to do with this discussion.

Since the PPC is in endpoint mode, the MSI hardware on the PPC won't be
used. The hardware is writable from the root complex via the PPC BAR0,
so I see no reason not to reuse it to trigger interrupts on the PPC from
the Root complex.

^ permalink raw reply

* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Eran Liberty @ 2010-10-11 10:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linux-pci, linuxppc-dev
In-Reply-To: <1286756363.2463.517.camel@pasglop>

Benjamin Herrenschmidt wrote:
>>  - pcie_portdrv_probe() will be called for every BRIDGE class PCI device. P2020 PCIe is a PCI-PCI BRIDGE class so no problem here. 
>>  - The code will continue to check that we have PCI_CAP_ID_EXP capability, which we have and continue to pcie_port_device_register().
>>  - Now ,the function pcie_port_device_register() will FAIL. It will fail because it will call assign_interrupt_mode(), return with PCIE_PORT_NO_IRQ, and giveup with a reasonable remark in the code
>> "/*
>>   * Don't use service devices that require interrupts if there is
>>   * no way to generate them.
>>   */"
>>
>> So now the question is why calling assign_interrupt_mode() with the P2020 PCIe ROOT device return empty? Well...
>>  - First assign_interrupt_mode() will test for PCIE_PORT_MSIX_MODE. Freescale PCIe does not support this...
>>  - Second attampt is made to discover PCIE_PORT_MSI_MODE, which Freescale should support but the PCIe PCI_CAP_ID_MSI capability is published on the device side of the bridge and NOT on the PCIe ROOT device, which is the one probed and thus fails.
>>  - Last it attempts to look at "dev->pin" in order to set PCIE_PORT_INTx_MODE. On top of being the less recommended way (the old way), The Freescale PCIE ROOT device pin is not set anywhere.
>>
>> Failing all those the probe fails and the AER service is not activated for the PCIE device.
>
> So the question boils down to how does the bridge generate the AER
> interrupts. This should be documented in the FSL docs no ? The MSI in
> the child/device should be unrelated (it's your device MSI) no ? So the
> question is where's the missing interrupt.
>
> If it's a SoC interrupt, coming from the device-tree, then perhaps the
> generic AER code should be extended to recognize those.
>
> Cheers,
> Ben.
>
I agree...

BUT if we take into consideration that:
1. Freescale is a serious dude in the hood and on the whole does a good 
job with its products and their Linux support.
2. The P2020 does state it has an MSI mechanism support (although one is 
not present as a PCIe capability header for some reason)
3. Errors in general and AER are major features in PCIe.
4. PCIe has been here quite a while and it is not new to Freescale or 
anyone else.
I am much more inclined to believe that I have missed something by a 
mile then that Freescale did. I just don't know what I am missing.

My device tree is a clone of "arch/ powerpc/ boot/ dts/ p2020rdb.dts"

It has a PCI node that looks like this:
----------------------------- snip -----------------------------
    pci0: pcie@ffe09000 {
        cell-index = <1>;
        compatible = "fsl,mpc8548-pcie";
        device_type = "pci";
        #interrupt-cells = <1>;
        #size-cells = <2>;
        #address-cells = <3>;
        reg = <0 0xffe09000 0 0x1000>;
        bus-range = <0 255>;
        ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
              0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
        clock-frequency = <33333333>;
        interrupt-parent = <&mpic>;
        interrupts = <25 2>;
        interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
        interrupt-map = <
            /* IDSEL 0x0 */
            0000 0x0 0x0 0x1 &mpic 0x4 0x1
            0000 0x0 0x0 0x2 &mpic 0x5 0x1
            0000 0x0 0x0 0x3 &mpic 0x6 0x1
            0000 0x0 0x0 0x4 &mpic 0x7 0x1
            >;
        pcie@0 {
            reg = <0x0 0x0 0x0 0x0 0x0>;
            #size-cells = <2>;
            #address-cells = <3>;
            device_type = "pci";
            ranges = <0x2000000 0x0 0xa0000000
                  0x2000000 0x0 0xa0000000
                  0x0 0x20000000

                  0x1000000 0x0 0x0
                  0x1000000 0x0 0x0
                  0x0 0x100000>;
        };
    };
----------------------------- snap -----------------------------

and under "soc" it has an MSI node that looks like that:
----------------------------- snip -----------------------------
        msi@41600 {
            compatible = "fsl,p2020-msi", "fsl,mpic-msi";
            reg = <0x41600 0x80>;
            msi-available-ranges = <0 0x100>;
            interrupts = <
                0xe0 0
                0xe1 0
                0xe2 0
                0xe3 0
                0xe4 0
                0xe5 0
                0xe6 0
                0xe7 0>;
            interrupt-parent = <&mpic>;
        };
----------------------------- snap -----------------------------

-- Liberty

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: tiejun.chen @ 2010-10-11  9:55 UTC (permalink / raw)
  To: david.hagood; +Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <8636b70ea34330679bebdaad187ccd68.squirrel@localhost>

david.hagood@gmail.com wrote:
> OK, using 224 as the MPIC interrupt number, and attempting to map it via
> irq_create_mapping(0,224) gives me a kernel seg fault:

This should not be correct without initialing MSI for MPIC host. As I comment on
another email, please refer to the file, arch/powerpc/sysdev/fsl_msi.c.

-Tiejun

> 
> Unable to handle kernel paging request for data at address 0x00000000
> Faulting instruction address: 0xc0016540
> Oops: Kernel access of bad area, sig: 11 [#1]
> PREEMPT SMP NR_CPUS=2 EP8641A
> Modules linked in: Endpoint_driver(+)
> NIP: c0016540 LR: c0050b38 CTR: c00163b8
> REGS: ef8c1ab0 TRAP: 0300   Not tainted  (2.6.26.2-ep1.10)
> MSR: 00001032 <ME,IR,DR>  CR: 24024482  XER: 00000000
> DAR: 00000000, DSISR: 40000000
> TASK = eedec6a0[60] 'insmod' THREAD: ef8c0000 CPU: 1
> GPR00: 00000000 ef8c1b60 eedec6a0 ffffffea 00000000 00000000 c035c17c
> 000000e0
> GPR08: 00400000 00000000 c035c020 00000000 24024422 100a7264 00000000
> 00000095
> GPR16: 00000095 00000000 0000000d 00000124 f102fd98 00000000 c004a4fc
> f102c000
> GPR24: 0000001a f1038400 00000000 c031e610 fffffffa 00009032 c031e5e0
> 000000e0
> NIP [c0016540] mpic_set_irq_type+0x188/0x1c4
> LR [c0050b38] set_irq_type+0x84/0xc8
> Call Trace:
> [ef8c1b60] [c0050b1c] set_irq_type+0x68/0xc8 (unreliable)
> [ef8c1b80] [c001572c] mpic_host_map+0xec/0xf4
> [ef8c1b90] [c00064a0] irq_setup_virq+0x60/0x98
> [ef8c1bb0] [c00065dc] irq_create_mapping+0x104/0x114
> [ef8c1bd0] [f1034798] Endpoint_device_ctor+0x258/0x3b8 [Endpoint_driver]
> 
> Reading the source (since these calls don't seem to have any other
> documentation), it *looks* like it ought to be valid to call
> irq_create_mapping with a null irq_host *host - which is good, since I
> can't see anything obvious that would give me some other irq_host (again,
> since none of this seems to be documented anywhere).
> 
> I am assuming the default host used by the system would be correct.
> 
> However, then I get this fault.
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: tiejun.chen @ 2010-10-11  9:51 UTC (permalink / raw)
  To: david.hagood; +Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <adaf806ee1c11621dbb51246bef0acd8.squirrel@localhost>

david.hagood@gmail.com wrote:
> First of all - where is all of this documented? There seems to be a great
> deal of "oral tradition" type knowledge here, but is any of it actually
> written down somewhere? (see below for examples)
> 
>> On Thu, 7 Oct 2010 15:12:26 -0500
>> This is asking for the 256th specifier in the interrupts property in
>> the mpic node -- not what you want.
> 
> That was from some of the previous emails in this thread.
> 
>> Ideally you would have a node for your device with an interrupt
>> specifier that you could look up with irq_of_parse_and_map().
> 
> OK, and how do these devices come into being? From what I can tell, they
> are defined by uBoot, and if uBoot doesn't define it, then you are out of
> luck.

You should define MSI device nodes on your target dts. And you can refer to the
file, mpc8572ds.dts.

Often U-Boot dose not generate MSI information and embed that to dtb.

> 
> But even assuming you can define these nodes at run time, as far as I can
> see, you are right back to the question of "and how do I know what the
> mappings are so I can create the node?" You haven't answered the question,
> you've just moved where you are asking it.

I think you can check fsl_msi.c to figure out what you want.
> 
> 
>> The vector/priority register (MSIVPR0) is at offset
>> 0x51c00.  Each interrupt source is 32 bytes.  The first interrupt
>> source is at 0x50000.
>>
>> So the interrupt number is (0x51c00 - 0x50000) / 32 = 224.
> 
> OK, so that's how you get the MPIC IRQ number. It's a pity that the key
> piece of information - "MPIC IRQ Numbers are defined by the interrupt
> vector table starting at 0x50000 and incrementing by 0x20 - see table 9.3
> of the MPD8641D manual for details" wasn't spelled out anywhere I could
> find.
> 
> Given the data I had: the kernel sources, the MPD8641D manual, and not
> much else, I had three unknowns:
> * a table of config registers, that could map an set of events into an
> arbitrary vector number.
> * The standard kernel "request_irq" API that takes that arbitrary vector
> number
> * A set of APIs (irq_of_parse_and_map(), irq_create_mapping) that were,
> for all intents, undocumented (just "here's the parameters", no
> description of when and how to use them), that took a ???? and returned a
> ???? (because, with the documentation I had, that's basically all I could
> say about them).

Firstly you should use irq_of_parse_and_map()/irq_create_mapping() to map the
real hardware irq to virtual irq. Then use request_irq() with the virtual irq to
hook your interrupt handler.

> 
> There was no documentation that said how to compute the MPIC interrupt
> vector, no documentation that said which API to use to convert that to an
> kernel IRQ, nothing.

Often most latest classic books/articles always use x86 code as an example to
clarify Linux. So you have to understand something on PPC via codes. But I think
you will benefit more information from the codes than documents :)

> 
>> BTW, the MSIs are already described in an msi node in the device tree.
> 
> As I stated previously - not that I can see. Neither does
> /proc/device_tree contain such a listing, nor does doing a
> "of_find_node_by_name(0,"msi");" nor "of_find_node_by_type(0,"msi");" find
> them.
> 
> It may be they are defined in PCI Root Complex mode, but again - I am
> writing code to handle Endpoint mode, which, as far as I can tell from the
> kernel sources, is NOT handled in any standardized way.

Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
previously said. And sounds Scott will do something to support EP for Freescale
chip.

Looks you want to your host root complex to trigger MSI to mpc8641 EP target? If
so I'm a bit confused since MSIs should be delivered to to the Root Complex
resided on your host.

Tiejun

> 
> 
> Again, it would be nice were this sort of thing documented somewhere. If
> it is, I'd love a link - I've tried every combination of search terms I
> can think of to find it to no avail.
> 
> If it isn't documented, might I suggest that either a) creating a
> dedicated "Programming PPC Embedded devices and their components under
> Linux" be created, or b) an appropriate chapter or chapters be drafted and
> submitted to the Linux Device Drivers book.
> 
> 
> Don't take this message the wrong way - I do want to say "THANK YOU FOR
> THE HELP!" - I am just trying to point out why somebody with a fair amount
> of Linux kernel experience and a great deal of general embedded experience
> is having great trouble doing a simple thing.
> 
> I'll try creating a mapping, binding to it, and seeing what happens.
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Benjamin Herrenschmidt @ 2010-10-11  0:19 UTC (permalink / raw)
  To: Eran Liberty
  Cc: Xianghua Xiao, linuxppc-dev, linux-pci, Tony Li, Linas Vepstas,
	ZHANG WEI
In-Reply-To: <4CADBD7B.3000506@extricom.com>


>  - pcie_portdrv_probe() will be called for every BRIDGE class PCI device. P2020 PCIe is a PCI-PCI BRIDGE class so no problem here. 
>  - The code will continue to check that we have PCI_CAP_ID_EXP capability, which we have and continue to pcie_port_device_register().
>  - Now ,the function pcie_port_device_register() will FAIL. It will fail because it will call assign_interrupt_mode(), return with PCIE_PORT_NO_IRQ, and giveup with a reasonable remark in the code
> "/*
>   * Don't use service devices that require interrupts if there is
>   * no way to generate them.
>   */"
> 
> So now the question is why calling assign_interrupt_mode() with the P2020 PCIe ROOT device return empty? Well...
>  - First assign_interrupt_mode() will test for PCIE_PORT_MSIX_MODE. Freescale PCIe does not support this...
>  - Second attampt is made to discover PCIE_PORT_MSI_MODE, which Freescale should support but the PCIe PCI_CAP_ID_MSI capability is published on the device side of the bridge and NOT on the PCIe ROOT device, which is the one probed and thus fails.
>  - Last it attempts to look at "dev->pin" in order to set PCIE_PORT_INTx_MODE. On top of being the less recommended way (the old way), The Freescale PCIE ROOT device pin is not set anywhere.
> 
> Failing all those the probe fails and the AER service is not activated for the PCIE device.

So the question boils down to how does the bridge generate the AER
interrupts. This should be documented in the FSL docs no ? The MSI in
the child/device should be unrelated (it's your device MSI) no ? So the
question is where's the missing interrupt.

If it's a SoC interrupt, coming from the device-tree, then perhaps the
generic AER code should be extended to recognize those.

Cheers,
Ben.

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: Benjamin Herrenschmidt @ 2010-10-10 23:41 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: avorontsov, miltonm, linux-kernel, paulus, scottwood, nacc, akpm,
	linuxppc-dev
In-Reply-To: <20101011000903R.fujita.tomonori@lab.ntt.co.jp>

On Mon, 2010-10-11 at 00:09 +0900, FUJITA Tomonori wrote:
> On Sat, 09 Oct 2010 10:44:53 +1100
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> 
> > On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> > > Also allow the coherent ops to be iommu if only the coherent mask is too
> > > small, mostly for driver that do not set set the coherent mask but also
> > > don't use the coherent api.
> > 
> > You are doing the transition at map_sg time which is a hot path, I don't
> > like that. Also you add all those "choose" variants of the dma ops...
> > not very nice at all.
> 
> Agreed, looks hacky.
> 
> 
> > You may want to look at the patches I posted to the list a while back
> > for doing direct DMA on Bimini:
> > 
> > [PATCH 1/2] powerpc/dma: Add optional platform override of dma_set_mask()
> 
> Would it be cleaner if each ppc dma_map_ops has the own set_dma_mask
> and dma_set_mask simply calls dma_map_ops->set_dma_mask?

I'm not sure I parse what you wrote above :-)

I did try with various methods back then, and what ended up sucking the
less was basically to hookup dma_set_mask() at the arch level.

In fact, it makes sense to the extent that the arch is the one that
knows that there are multiple regions configured potentially with
different capabilities.

You can still do the switch within the dma_ops->set_dma_mask if you want
I suppose, especially if you end up hitting different attribute regions
within a single bus or such but from my experience, it gets really hacky
with multiple ops structures etc...
> 
> > [PATCH 2/2] powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe
> 

Cheers,
Ben.

^ permalink raw reply

* Re: Pegasos i8042 broken again
From: pacman @ 2010-10-10 17:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1286696147.2463.499.camel@pasglop>

Benjamin Herrenschmidt writes:
> 
> Those things really suck. They absolutely refuse to fix their FW for
> reasons I never quite managed to figure out.

The last time around, they did release a firmware patch (pegasos-dts-20071018)
to fix up the device tree enough to satisfy the kernel. Now that the kernel
has become dissatisfied again, maybe another patch will appear.

> 
> At this stage, I'd say the best is to add yet another pegasos workaround
> in prom_init that adds the missing compatible property.

This one would be more complex than the other fixes in prom_init. It's not
just the compatible property that's missing. The 8042 node in the device tree
has no children.

-- 
Alan Curry

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: FUJITA Tomonori @ 2010-10-10 15:09 UTC (permalink / raw)
  To: benh
  Cc: avorontsov, miltonm, linux-kernel, fujita.tomonori, paulus,
	scottwood, nacc, akpm, linuxppc-dev
In-Reply-To: <1286581493.2463.428.camel@pasglop>

On Sat, 09 Oct 2010 10:44:53 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> > Also allow the coherent ops to be iommu if only the coherent mask is too
> > small, mostly for driver that do not set set the coherent mask but also
> > don't use the coherent api.
> 
> You are doing the transition at map_sg time which is a hot path, I don't
> like that. Also you add all those "choose" variants of the dma ops...
> not very nice at all.

Agreed, looks hacky.


> You may want to look at the patches I posted to the list a while back
> for doing direct DMA on Bimini:
> 
> [PATCH 1/2] powerpc/dma: Add optional platform override of dma_set_mask()

Would it be cleaner if each ppc dma_map_ops has the own set_dma_mask
and dma_set_mask simply calls dma_map_ops->set_dma_mask?


> [PATCH 2/2] powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe

^ permalink raw reply

* Re: Pegasos i8042 broken again
From: Gerhard Pircher @ 2010-10-10 12:26 UTC (permalink / raw)
  To: pacman; +Cc: linuxppc-dev
In-Reply-To: <1286696147.2463.499.camel@pasglop>


On Sat, 2010-10-09 at 20:37 -0500, pacman@kosh.dhis.org wrote:
> Pegasos has no keyboard again. I blame commit
> 540c6c392f01887dcc96bef0a41e63e6c1334f01, which tries to find i8042 IRQs
> inthe device-tree but doesn't fall back to the old hardcoded 1 and 12 in
> all failure cases.
> 
> Specifically, the case where the device-tree contains nothing matching
> pnpPNP,303 or pnpPNP,f03 doesn't seem to be handled well. It sort of
> falls through to the old code, but leaves the IRQs set to 0.
> 
> The last time something like this happened, I submitted a patch:
> http://lists.ozlabs.org/pipermail/linuxppc-dev/2007-July/039988.html
> which got committed, but afterward I was scolded for working around a
> bug instead of fixing it in nvramrc.
> 
> This time I just won't send my workaround patch, at least until it's
> decided that the kernel should be made to understand the device-tree as
> is.
> If it's decided instead that the firmware should be patched... well I
> just don't feel comfortable inventing my own patch for nvramrc, since
> it's written in a language I don't know and presumably could brick the
> machine if I get it wrong. Also I'm not even sure what the kernel is
> expecting to find there.

Is this a Pegasos 1 or Pegasos 2? I'm just curious, because some Pegasos 1
users told me that newer Linux kernels don't even boot on their machines.

regards,

Gerhard
-- 
Neu: GMX De-Mail - Einfach wie E-Mail, sicher wie ein Brief!  
Jetzt De-Mail-Adresse reservieren: http://portal.gmx.net/de/go/demail

^ permalink raw reply

* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Eran Liberty @ 2010-10-10 10:02 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linux-pci, linuxppc-dev
In-Reply-To: <948C4143-91C1-45AD-9E0A-82E3F394B181@kernel.crashing.org>

Kumar Gala wrote:
> On Oct 7, 2010, at 7:30 AM, Eran Liberty wrote:
>
>   
>> Dear Penguins,
>>
>> SHORT:
>> There is a BUG in the current code design / Freescale P2020/85xx PCIe design that prevent it from registering to the PCIe AER... or that I have missed something :) ..
>>
>> LESS SHORT:
>> I am in the process of a Freescale P2020 based board bring up. P2020 is basically two 85xx processors and their peripherals share most features.
>>
>> PCIe has a very extensive error reporting section and the Kernel already has a very nice looking Advanced Error Reporting driver.
>>
>> I encounter difficulties trying to connect the P2020/85xx PCIe device to this AER service driver.
>>
>> My technical findings follows:
>>
>> - pcie_portdrv_probe() will be called for every BRIDGE class PCI device. P2020 PCIe is a PCI-PCI BRIDGE class so no problem here. - The code will continue to check that we have PCI_CAP_ID_EXP capability, which we have and continue to pcie_port_device_register().
>> - Now ,the function pcie_port_device_register() will FAIL. It will fail because it will call assign_interrupt_mode(), return with PCIE_PORT_NO_IRQ, and giveup with a reasonable remark in the code
>> "/*
>> * Don't use service devices that require interrupts if there is
>> * no way to generate them.
>> */"
>>
>> So now the question is why calling assign_interrupt_mode() with the P2020 PCIe ROOT device return empty? Well...
>> - First assign_interrupt_mode() will test for PCIE_PORT_MSIX_MODE. Freescale PCIe does not support this...
>> - Second attampt is made to discover PCIE_PORT_MSI_MODE, which Freescale should support but the PCIe PCI_CAP_ID_MSI capability is published on the device side of the bridge and NOT on the PCIe ROOT device, which is the one probed and thus fails.
>> - Last it attempts to look at "dev->pin" in order to set PCIE_PORT_INTx_MODE. On top of being the less recommended way (the old way), The Freescale PCIE ROOT device pin is not set anywhere.
>>
>> Failing all those the probe fails and the AER service is not activated for the PCIE device.
>>
>> QUESTION:
>> 1. What am I missing?
>> 2. Has anyone enabled the AER PCIe service for P2020/MPC85xx?
>> 3. Should the PCIe ROOT end report MSI capabilities or should the device end report itself as bridge ???
>>
>> -- Liberty
>>     
>
> Do you have some code that enables AER on P2020.  If so it might be easier to see what's going on.
>
>
>   
> - k
>
>
The code that enables the AER is the problem. The kernel fails to probe 
my devices into the AER sevice. I can brutally hack my kernel to 
register the AER service. I copy the dev->irq and dev->pin from the 
child device to the bridge device. This will get the bridge device 
registered BUT it is not working and this hack is surly not a solution.

Here is a snap shot of my un-hacked devices, hopefully it will clarify 
the situation:

~ # ls -la /sys/bus/pci/devices/
drwxr-xr-x    2 root     root            0 Jan  3 17:25 .
drwxr-xr-x    5 root     root            0 Jan  3 17:25 ..
lrwxrwxrwx    1 root     root            0 Jan  3 17:25 0001:01:00.0 -> 
../../../devices/pci0001:01/0001:01:00.0
lrwxrwxrwx    1 root     root            0 Jan  3 17:25 0001:02:00.0 -> 
../../../devices/pci0001:01/0001:01:00.0/0001:02:00.0

"0001:01:00.0" is the PCIe PCI-PCI bridge side (Freescale's side)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/vendor
0x1957 (PCI_VENDOR_ID_FREESCALE)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/device
0x0071 (PCI_DEVICE_ID_P2020)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/class
0x060400 (PCI_CLASS_BRIDGE_PCI)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/enable
1
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/irq
0
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/msi_bus
1
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/resource
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x000000000000ffff 0x0000000000000100
0x00000000c0000000 0x00000000dfffffff 0x0000000000000200
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
~ # hexdump  /sys/bus/pci/devices/0001\:01\:00.0/config
0000000 5719 7100 0601 1000 1000 200b 0800 0100 (PCI Compatible 
Configuration Headers)
0000010 0000 f0ff 0000 0000 0002 0200 0000 0000
0000020 00c0 f0df f1ff 0100 0000 0000 0000 0000
0000030 0000 0000 4400 0000 0000 0000 0000 0000
0000040 0000 0000 014c 02fe 0000 0000 1000 4100 (Power Mgmt 
Capabilities) , (0x4C: PCI Express Capabilities)
0000050 0100 0000 3e58 0000 41d4 0300 0800 4100
0000060 c007 0000 c003 4000 0000 0000 0000 0000
0000070 0000 0000 0000 0000 0000 0000 0000 0000
*
0000100 0100 0100 0000 0000 0000 0000 1020 0600 (Advanced Error 
Reporting Capability)
0000110 0000 0000 0000 0000 a000 0000 0000 0000
0000120 0000 0000 0000 0000 0000 0000 0000 0000
*
0000400 0000 0000 1600 0000 e204 0000 0000 0000 (PCI Express Controller 
Internal CSRs)
0000410 0800 0000 0000 0000 0000 0000 4040 0000
0000420 0000 0000 0000 0000 0000 0000 0000 0000
0000430 0000 0000 0000 0000 8300 6300 9ba0 0900
0000440 1000 0000 0000 0000 0000 0000 0000 0000
0000450 ced7 1400 201e fc01 0000 0000 5c0c 0000
0000460 0000 0000 0000 0000 0000 0000 0000 0000
0000470 5719 7100 1000 200b 0000 0000 0100 0000
0000480 443d 0000 0000 0000 f007 0000 0000 0000
0000490 c007 0000 0000 0000 0000 0000 0000 0000
00004a0 0000 0000 0000 0000 0000 0000 0000 0000
00004b0 0000 0000 0000 0000 2804 0180 8520 0000
00004c0 ff00 0000 0000 0000 0000 0000 1100 0000
00004d0 0000 0000 0000 0000 0000 0000 0000 0000
00004e0 0000 0000 0101 0000 0101 0000 0000 0000
00004f0 4a00 0001 0200 0004 0000 0000 0800 0000
0000500 0000 0000 0000 0000 0000 0000 0000 0000
0000510 0000 0000 0000 0000 8300 0000 0000 0000
0000520 0000 0000 0000 0000 0000 0000 0000 0000
*
0000540 0000 0000 0001 0202 0000 0000 0500 0000
0000550 0000 0000 0000 0000 0000 0000 0000 0000
*
0000590 d0cf 3200 0000 0000 0000 0000 0000 0000
00005a0 3f00 0000 0000 0000 0000 0000 0000 0000
00005b0 0000 0000 0000 0000 0000 0000 0000 0000
*
0001000

Now here is the other side of the tunnel, "0001:02:00.0" (our device)
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/vendor
0x1234 (Just a number i picked up and told the HW dudes to put into the 
device... don't look it up :) )
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/device
0x0002
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/class
0xff0000
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/enable
0
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/irq
16
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/msi_bus
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/resource
0x00000000c0000000 0x00000000c007ffff 0x0000000000020200
0x00000000c0080000 0x00000000c00fffff 0x0000000000020200
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
~ # hexdump /sys/bus/pci/devices/0001\:02\:00.0/config
0000000 3412 0200 0600 1000 0100 00ff 0800 0000
0000010 0000 00c0 0000 08c0 0000 0000 0000 0000
0000020 0000 0000 0000 0000 0000 0000 3412 0200
0000030 0000 0000 5000 0000 0000 0000 0001 0000
0000040 0000 0000 6061 0002 0000 0000 0000 0000
0000050 0578 8400 0000 0000 0000 0000 0000 0000
0000060 0000 0000 0000 0000 1178 0000 0000 0000
0000070 0000 0000 0000 0000 0180 0300 0800 0000
0000080 1000 0100 0180 3c00 3058 0000 41f4 0301
0000090 0000 4110 0000 0400 c003 0000 0000 0000
00000a0 0000 0000 0000 0000 0000 0000 0000 0000
00000b0 0100 0100 0000 0000 0000 0000 0000 0000
00000c0 0000 0000 0000 0000 0000 0000 0000 0000
*
0000100 0200 0180 0000 0000 0000 0000 0000 0000
0000110 0000 0000 ff00 0080 0000 0000 0000 0000
0000120 0000 0000 0000 0000 0000 0000 0000 0000
*
0000800 0100 0100 0000 0000 0000 0000 3120 0600
0000810 0000 0000 0020 0000 0000 0000 0000 0000
0000820 0000 0000 0000 0000 0000 0000 0000 0000
*
0001000

NOW... As it is, under "/sys/bus/pci_express/devices/" you will find no 
devices. Debug prints which I have stuffed into pcie_portdrv_probe() 
shows that: "0001:01:00" is probed and fails to register for lacking a 
suitable interrupt mechanism as described by the previous mail, and 
"0001:02:00" fails to probe since it is not a PCI ROOT port.
As said, if I hack and slash and mainly cheat I can persuade the Kernel 
not to fail the probe and then I get these:

~ # ls -la /sys/bus/pci_express/devices/
drwxr-xr-x    2 root     root            0 Jan  3 17:49 .
drwxr-xr-x    4 root     root            0 Jan  3 17:49 ..
lrwxrwxrwx    1 root     root            0 Jan  3 17:49 
0001:01:00.0:pcie01 -> 
../../../devices/pci0001:01/0001:01:00.0/0001:01:00.0:pcie01
lrwxrwxrwx    1 root     root            0 Jan  3 17:49 
0001:01:00.0:pcie02 -> 
../../../devices/pci0001:01/0001:01:00.0/0001:01:00.0:pcie02

This is NOT functional as I have crippled the kernel on the way but I 
think this is  what I am missing and maybe my goal.

-- Liberty

^ permalink raw reply

* Re: Pegasos i8042 broken again
From: Benjamin Herrenschmidt @ 2010-10-10  7:35 UTC (permalink / raw)
  To: pacman; +Cc: linuxppc-dev
In-Reply-To: <20101010013755.1697.qmail@kosh.dhis.org>

On Sat, 2010-10-09 at 20:37 -0500, pacman@kosh.dhis.org wrote:
> Pegasos has no keyboard again. I blame commit
> 540c6c392f01887dcc96bef0a41e63e6c1334f01, which tries to find i8042 IRQs in
> the device-tree but doesn't fall back to the old hardcoded 1 and 12 in all
> failure cases.
> 
> Specifically, the case where the device-tree contains nothing matching
> pnpPNP,303 or pnpPNP,f03 doesn't seem to be handled well. It sort of falls
> through to the old code, but leaves the IRQs set to 0.
> 
> The last time something like this happened, I submitted a patch:
> http://lists.ozlabs.org/pipermail/linuxppc-dev/2007-July/039988.html
> which got committed, but afterward I was scolded for working around a bug
> instead of fixing it in nvramrc.
> 
> This time I just won't send my workaround patch, at least until it's decided
> that the kernel should be made to understand the device-tree as is.
> 
> If it's decided instead that the firmware should be patched... well I just
> don't feel comfortable inventing my own patch for nvramrc, since it's written
> in a language I don't know and presumably could brick the machine if I get it
> wrong. Also I'm not even sure what the kernel is expecting to find there. 

Those things really suck. They absolutely refuse to fix their FW for
reasons I never quite managed to figure out.

At this stage, I'd say the best is to add yet another pegasos workaround
in prom_init that adds the missing compatible property.

Cheers,
Ben.

^ permalink raw reply

* Pegasos i8042 broken again
From: pacman @ 2010-10-10  1:37 UTC (permalink / raw)
  To: linuxppc-dev

Pegasos has no keyboard again. I blame commit
540c6c392f01887dcc96bef0a41e63e6c1334f01, which tries to find i8042 IRQs in
the device-tree but doesn't fall back to the old hardcoded 1 and 12 in all
failure cases.

Specifically, the case where the device-tree contains nothing matching
pnpPNP,303 or pnpPNP,f03 doesn't seem to be handled well. It sort of falls
through to the old code, but leaves the IRQs set to 0.

The last time something like this happened, I submitted a patch:
http://lists.ozlabs.org/pipermail/linuxppc-dev/2007-July/039988.html
which got committed, but afterward I was scolded for working around a bug
instead of fixing it in nvramrc.

This time I just won't send my workaround patch, at least until it's decided
that the kernel should be made to understand the device-tree as is.

If it's decided instead that the firmware should be patched... well I just
don't feel comfortable inventing my own patch for nvramrc, since it's written
in a language I don't know and presumably could brick the machine if I get it
wrong. Also I'm not even sure what the kernel is expecting to find there.

-- 
Alan Curry

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-09 17:03 UTC (permalink / raw)
  To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101007152626.4e834d43@udp111988uds.am.freescale.net>

OK, using 224 as the MPIC interrupt number, and attempting to map it via
irq_create_mapping(0,224) gives me a kernel seg fault:

Unable to handle kernel paging request for data at address 0x00000000
Faulting instruction address: 0xc0016540
Oops: Kernel access of bad area, sig: 11 [#1]
PREEMPT SMP NR_CPUS=2 EP8641A
Modules linked in: Endpoint_driver(+)
NIP: c0016540 LR: c0050b38 CTR: c00163b8
REGS: ef8c1ab0 TRAP: 0300   Not tainted  (2.6.26.2-ep1.10)
MSR: 00001032 <ME,IR,DR>  CR: 24024482  XER: 00000000
DAR: 00000000, DSISR: 40000000
TASK = eedec6a0[60] 'insmod' THREAD: ef8c0000 CPU: 1
GPR00: 00000000 ef8c1b60 eedec6a0 ffffffea 00000000 00000000 c035c17c
000000e0
GPR08: 00400000 00000000 c035c020 00000000 24024422 100a7264 00000000
00000095
GPR16: 00000095 00000000 0000000d 00000124 f102fd98 00000000 c004a4fc
f102c000
GPR24: 0000001a f1038400 00000000 c031e610 fffffffa 00009032 c031e5e0
000000e0
NIP [c0016540] mpic_set_irq_type+0x188/0x1c4
LR [c0050b38] set_irq_type+0x84/0xc8
Call Trace:
[ef8c1b60] [c0050b1c] set_irq_type+0x68/0xc8 (unreliable)
[ef8c1b80] [c001572c] mpic_host_map+0xec/0xf4
[ef8c1b90] [c00064a0] irq_setup_virq+0x60/0x98
[ef8c1bb0] [c00065dc] irq_create_mapping+0x104/0x114
[ef8c1bd0] [f1034798] Endpoint_device_ctor+0x258/0x3b8 [Endpoint_driver]

Reading the source (since these calls don't seem to have any other
documentation), it *looks* like it ought to be valid to call
irq_create_mapping with a null irq_host *host - which is good, since I
can't see anything obvious that would give me some other irq_host (again,
since none of this seems to be documented anywhere).

I am assuming the default host used by the system would be correct.

However, then I get this fault.

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-09 15:52 UTC (permalink / raw)
  To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101007152626.4e834d43@udp111988uds.am.freescale.net>

First of all - where is all of this documented? There seems to be a great
deal of "oral tradition" type knowledge here, but is any of it actually
written down somewhere? (see below for examples)

> On Thu, 7 Oct 2010 15:12:26 -0500
> This is asking for the 256th specifier in the interrupts property in
> the mpic node -- not what you want.

That was from some of the previous emails in this thread.

> Ideally you would have a node for your device with an interrupt
> specifier that you could look up with irq_of_parse_and_map().

OK, and how do these devices come into being? From what I can tell, they
are defined by uBoot, and if uBoot doesn't define it, then you are out of
luck.

But even assuming you can define these nodes at run time, as far as I can
see, you are right back to the question of "and how do I know what the
mappings are so I can create the node?" You haven't answered the question,
you've just moved where you are asking it.


> The vector/priority register (MSIVPR0) is at offset
> 0x51c00.  Each interrupt source is 32 bytes.  The first interrupt
> source is at 0x50000.
>
> So the interrupt number is (0x51c00 - 0x50000) / 32 = 224.

OK, so that's how you get the MPIC IRQ number. It's a pity that the key
piece of information - "MPIC IRQ Numbers are defined by the interrupt
vector table starting at 0x50000 and incrementing by 0x20 - see table 9.3
of the MPD8641D manual for details" wasn't spelled out anywhere I could
find.

Given the data I had: the kernel sources, the MPD8641D manual, and not
much else, I had three unknowns:
* a table of config registers, that could map an set of events into an
arbitrary vector number.
* The standard kernel "request_irq" API that takes that arbitrary vector
number
* A set of APIs (irq_of_parse_and_map(), irq_create_mapping) that were,
for all intents, undocumented (just "here's the parameters", no
description of when and how to use them), that took a ???? and returned a
???? (because, with the documentation I had, that's basically all I could
say about them).

There was no documentation that said how to compute the MPIC interrupt
vector, no documentation that said which API to use to convert that to an
kernel IRQ, nothing.

> BTW, the MSIs are already described in an msi node in the device tree.

As I stated previously - not that I can see. Neither does
/proc/device_tree contain such a listing, nor does doing a
"of_find_node_by_name(0,"msi");" nor "of_find_node_by_type(0,"msi");" find
them.

It may be they are defined in PCI Root Complex mode, but again - I am
writing code to handle Endpoint mode, which, as far as I can tell from the
kernel sources, is NOT handled in any standardized way.


Again, it would be nice were this sort of thing documented somewhere. If
it is, I'd love a link - I've tried every combination of search terms I
can think of to find it to no avail.

If it isn't documented, might I suggest that either a) creating a
dedicated "Programming PPC Embedded devices and their components under
Linux" be created, or b) an appropriate chapter or chapters be drafted and
submitted to the Linux Device Drivers book.


Don't take this message the wrong way - I do want to say "THANK YOU FOR
THE HELP!" - I am just trying to point out why somebody with a fair amount
of Linux kernel experience and a great deal of general embedded experience
is having great trouble doing a simple thing.

I'll try creating a mapping, binding to it, and seeing what happens.

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: Benjamin Herrenschmidt @ 2010-10-08 23:44 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: Anton Vorontsov, miltonm, linux-kernel, FUJITA Tomonori,
	Paul Mackerras, Scott Wood, Andrew Morton, linuxppc-dev
In-Reply-To: <1286559192-10898-4-git-send-email-nacc@us.ibm.com>

On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> Also allow the coherent ops to be iommu if only the coherent mask is too
> small, mostly for driver that do not set set the coherent mask but also
> don't use the coherent api.

You are doing the transition at map_sg time which is a hot path, I don't
like that. Also you add all those "choose" variants of the dma ops...
not very nice at all.

You may want to look at the patches I posted to the list a while back
for doing direct DMA on Bimini:

[PATCH 1/2] powerpc/dma: Add optional platform override of dma_set_mask()
[PATCH 2/2] powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe

Cheers,
Ben.

> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> ---
>  arch/powerpc/include/asm/dma-mapping.h |    2 +
>  arch/powerpc/kernel/Makefile           |    2 +-
>  arch/powerpc/kernel/dma-choose64.c     |  167 ++++++++++++++++++++++++++++++++
>  3 files changed, 170 insertions(+), 1 deletions(-)
>  create mode 100644 arch/powerpc/kernel/dma-choose64.c
> 
> diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
> index 644103a..9ffb16a 100644
> --- a/arch/powerpc/include/asm/dma-mapping.h
> +++ b/arch/powerpc/include/asm/dma-mapping.h
> @@ -68,6 +68,8 @@ static inline unsigned long device_to_mask(struct device *dev)
>   */
>  #ifdef CONFIG_PPC64
>  extern struct dma_map_ops dma_iommu_ops;
> +extern struct dma_map_ops dma_choose64_ops;
> +extern struct dma_map_ops dma_iommu_coherent_ops;
>  #endif
>  extern struct dma_map_ops dma_direct_ops;
>  
> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> index 1dda701..21b8ea1 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -82,7 +82,7 @@ obj-y				+= time.o prom.o traps.o setup-common.o \
>  				   udbg.o misc.o io.o dma.o \
>  				   misc_$(CONFIG_WORD_SIZE).o
>  obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
> -obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
> +obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o dma-choose64.o
>  obj-$(CONFIG_KGDB)		+= kgdb.o
>  obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE)	+= prom_init.o
>  obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
> diff --git a/arch/powerpc/kernel/dma-choose64.c b/arch/powerpc/kernel/dma-choose64.c
> new file mode 100644
> index 0000000..17c716f
> --- /dev/null
> +++ b/arch/powerpc/kernel/dma-choose64.c
> @@ -0,0 +1,167 @@
> +/*
> + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
> + *
> + * Provide default implementations of the DMA mapping callbacks for
> + * directly mapped busses.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/bug.h>
> +
> +/*
> + * DMA operations that choose between a 64-bit direct mapping and and iommu
> + *
> + * This set of dma ops chooses between directing to a static 1:1 mapping
> + * that may require a 64 bit address and a iommu based on the declared
> + * streaming and coherent masks for the device.  The choice is made on
> + * the first dma map call.
> + */
> +
> +/* first BUG ops for calls out of sequence */
> +
> +void *dma_bug_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	BUG();
> +
> +	return NULL;
> +}
> +
> +void dma_bug_free_coherent(struct device *dev, size_t size,
> +			      void *vaddr, dma_addr_t dma_handle)
> +{
> +	BUG();
> +}
> +
> +static int dma_bug_dma_supported(struct device *dev, u64 mask)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +static int dma_bug_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +
> +static void dma_bug_unmap_sg(struct device *dev, struct scatterlist *sg,
> +				int nents, enum dma_data_direction direction,
> +				struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +static dma_addr_t dma_bug_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return DMA_ERROR_CODE;
> +}
> +
> +
> +static void dma_bug_unmap_page(struct device *dev,
> +					 dma_addr_t dma_address,
> +					 size_t size,
> +					 enum dma_data_direction direction,
> +					 struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +
> +static struct dma_map_ops *choose(struct device *dev)
> +{
> +	if (dma_direct_ops.dma_supported(dev, device_to_mask(dev))) {
> +		if (dma_direct_ops.dma_supported(dev, dev->coherent_dma_mask))
> +			return &dma_direct_ops;
> +		return &dma_iommu_coherent_ops;
> +	}
> +	return &dma_iommu_ops;
> +}
> +
> +void *dma_choose64_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->alloc_coherent(dev, size, dma_handle, flag);
> +}
> +
> +static int dma_choose64_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_sg(dev, sgl, nents, direction, attrs);
> +}
> +
> +
> +static int dma_choose64_dma_supported(struct device *dev, u64 mask)
> +{
> +	return dma_direct_ops.dma_supported(dev, mask) ||
> +		dma_iommu_ops.dma_supported(dev, mask);
> +}
> +
> +static dma_addr_t dma_choose64_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_page(dev, page, offset, size, dir, attrs);
> +}
> +
> +struct dma_map_ops dma_choose64_ops = {
> +	.alloc_coherent	= dma_choose64_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_choose64_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_choose64_dma_supported,
> +	.map_page	= dma_choose64_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_choose64_ops);
> +
> +/* set these up to BUG() until we initialze them in the arch initcall below */
> +struct dma_map_ops dma_iommu_coherent_ops = {
> +	.alloc_coherent	= dma_bug_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_bug_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_bug_dma_supported,
> +	.map_page	= dma_bug_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_iommu_coherent_ops);
> +
> +static int setup_choose64_ops(void)
> +{
> +	dma_iommu_coherent_ops = dma_direct_ops;
> +	dma_iommu_coherent_ops.alloc_coherent = dma_iommu_ops.alloc_coherent;
> +	dma_iommu_coherent_ops.free_coherent = dma_iommu_ops.free_coherent;
> +
> +	/* should we be stricter? */
> +	dma_iommu_coherent_ops.dma_supported = dma_choose64_dma_supported;
> +
> +	return 0;
> +}
> +arch_initcall(setup_choose64_ops);

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: Benjamin Herrenschmidt @ 2010-10-08 23:43 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: Anton Vorontsov, miltonm, linux-kernel, FUJITA Tomonori,
	Paul Mackerras, Scott Wood, Andrew Morton, linuxppc-dev
In-Reply-To: <1286559192-10898-4-git-send-email-nacc@us.ibm.com>

On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> Also allow the coherent ops to be iommu if only the coherent mask is too
> small, mostly for driver that do not set set the coherent mask but also
> don't use the coherent api.

You are doing the transition at map_sg time which is a hot path, I don't
like that. Also you add all those "choose" variants of the dma ops...
not very nice at all.

You may want to look at the patches I posted to the list a while back
for doing direct DMA on Bimini:

> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> ---
>  arch/powerpc/include/asm/dma-mapping.h |    2 +
>  arch/powerpc/kernel/Makefile           |    2 +-
>  arch/powerpc/kernel/dma-choose64.c     |  167 ++++++++++++++++++++++++++++++++
>  3 files changed, 170 insertions(+), 1 deletions(-)
>  create mode 100644 arch/powerpc/kernel/dma-choose64.c
> 
> diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
> index 644103a..9ffb16a 100644
> --- a/arch/powerpc/include/asm/dma-mapping.h
> +++ b/arch/powerpc/include/asm/dma-mapping.h
> @@ -68,6 +68,8 @@ static inline unsigned long device_to_mask(struct device *dev)
>   */
>  #ifdef CONFIG_PPC64
>  extern struct dma_map_ops dma_iommu_ops;
> +extern struct dma_map_ops dma_choose64_ops;
> +extern struct dma_map_ops dma_iommu_coherent_ops;
>  #endif
>  extern struct dma_map_ops dma_direct_ops;
>  
> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> index 1dda701..21b8ea1 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -82,7 +82,7 @@ obj-y				+= time.o prom.o traps.o setup-common.o \
>  				   udbg.o misc.o io.o dma.o \
>  				   misc_$(CONFIG_WORD_SIZE).o
>  obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
> -obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
> +obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o dma-choose64.o
>  obj-$(CONFIG_KGDB)		+= kgdb.o
>  obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE)	+= prom_init.o
>  obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
> diff --git a/arch/powerpc/kernel/dma-choose64.c b/arch/powerpc/kernel/dma-choose64.c
> new file mode 100644
> index 0000000..17c716f
> --- /dev/null
> +++ b/arch/powerpc/kernel/dma-choose64.c
> @@ -0,0 +1,167 @@
> +/*
> + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
> + *
> + * Provide default implementations of the DMA mapping callbacks for
> + * directly mapped busses.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/bug.h>
> +
> +/*
> + * DMA operations that choose between a 64-bit direct mapping and and iommu
> + *
> + * This set of dma ops chooses between directing to a static 1:1 mapping
> + * that may require a 64 bit address and a iommu based on the declared
> + * streaming and coherent masks for the device.  The choice is made on
> + * the first dma map call.
> + */
> +
> +/* first BUG ops for calls out of sequence */
> +
> +void *dma_bug_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	BUG();
> +
> +	return NULL;
> +}
> +
> +void dma_bug_free_coherent(struct device *dev, size_t size,
> +			      void *vaddr, dma_addr_t dma_handle)
> +{
> +	BUG();
> +}
> +
> +static int dma_bug_dma_supported(struct device *dev, u64 mask)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +static int dma_bug_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +
> +static void dma_bug_unmap_sg(struct device *dev, struct scatterlist *sg,
> +				int nents, enum dma_data_direction direction,
> +				struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +static dma_addr_t dma_bug_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return DMA_ERROR_CODE;
> +}
> +
> +
> +static void dma_bug_unmap_page(struct device *dev,
> +					 dma_addr_t dma_address,
> +					 size_t size,
> +					 enum dma_data_direction direction,
> +					 struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +
> +static struct dma_map_ops *choose(struct device *dev)
> +{
> +	if (dma_direct_ops.dma_supported(dev, device_to_mask(dev))) {
> +		if (dma_direct_ops.dma_supported(dev, dev->coherent_dma_mask))
> +			return &dma_direct_ops;
> +		return &dma_iommu_coherent_ops;
> +	}
> +	return &dma_iommu_ops;
> +}
> +
> +void *dma_choose64_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->alloc_coherent(dev, size, dma_handle, flag);
> +}
> +
> +static int dma_choose64_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_sg(dev, sgl, nents, direction, attrs);
> +}
> +
> +
> +static int dma_choose64_dma_supported(struct device *dev, u64 mask)
> +{
> +	return dma_direct_ops.dma_supported(dev, mask) ||
> +		dma_iommu_ops.dma_supported(dev, mask);
> +}
> +
> +static dma_addr_t dma_choose64_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_page(dev, page, offset, size, dir, attrs);
> +}
> +
> +struct dma_map_ops dma_choose64_ops = {
> +	.alloc_coherent	= dma_choose64_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_choose64_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_choose64_dma_supported,
> +	.map_page	= dma_choose64_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_choose64_ops);
> +
> +/* set these up to BUG() until we initialze them in the arch initcall below */
> +struct dma_map_ops dma_iommu_coherent_ops = {
> +	.alloc_coherent	= dma_bug_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_bug_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_bug_dma_supported,
> +	.map_page	= dma_bug_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_iommu_coherent_ops);
> +
> +static int setup_choose64_ops(void)
> +{
> +	dma_iommu_coherent_ops = dma_direct_ops;
> +	dma_iommu_coherent_ops.alloc_coherent = dma_iommu_ops.alloc_coherent;
> +	dma_iommu_coherent_ops.free_coherent = dma_iommu_ops.free_coherent;
> +
> +	/* should we be stricter? */
> +	dma_iommu_coherent_ops.dma_supported = dma_choose64_dma_supported;
> +
> +	return 0;
> +}
> +arch_initcall(setup_choose64_ops);

^ permalink raw reply

* Re: [RFC PATCH 02/11] ppc: allow direct and iommu to coexist
From: Benjamin Herrenschmidt @ 2010-10-08 23:38 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: FUJITA Tomonori, linux-kernel, miltonm, Paul Mackerras,
	Andrew Morton, linuxppc-dev
In-Reply-To: <1286559192-10898-3-git-send-email-nacc@us.ibm.com>

On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> Replace the union with just the multiple fields, ifdef on CONFIG_PPC64.
> 
> Future pseries boxes will allow a 64 bit dma mapping covering all
> memory, coexisting with a smaller iommu window in 32 bit pci space.
> 
> The cell fixed mapping would also like both to coexist.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> ---
> I used the ifdef guard of CONFIG_PPC64 according to the current makefile
> for iommu.c.  One set is burried in the middle of iommu.h.

I dislike the ifdef's ...

Also, why remove the union ? IE. Do we really them to co-exist for a
given device ? I'm doing something similar for another (not released
yet) processor where I'm flicking between direct and iommu at
set_dma_mask time, it's easy enough to change the union content.

Cheers,
Ben.

> ---
>  arch/powerpc/include/asm/device.h      |   14 ++++++--------
>  arch/powerpc/include/asm/dma-mapping.h |    4 ++--
>  arch/powerpc/include/asm/iommu.h       |    6 ++++--
>  3 files changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h
> index 16d25c0..ed883ea 100644
> --- a/arch/powerpc/include/asm/device.h
> +++ b/arch/powerpc/include/asm/device.h
> @@ -19,14 +19,12 @@ struct dev_archdata {
>  	/* DMA operations on that device */
>  	struct dma_map_ops	*dma_ops;
>  
> -	/*
> -	 * When an iommu is in use, dma_data is used as a ptr to the base of the
> -	 * iommu_table.  Otherwise, it is a simple numerical offset.
> -	 */
> -	union {
> -		dma_addr_t	dma_offset;
> -		void		*iommu_table_base;
> -	} dma_data;
> +	/* dma_offset is used by swiotlb and direct dma ops, but no iommu */
> +	dma_addr_t	dma_offset;
> +
> +#ifdef CONFIG_PPC64
> +	void		*iommu_table_base;
> +#endif
>  
>  #ifdef CONFIG_SWIOTLB
>  	dma_addr_t		max_direct_dma_addr;
> diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
> index 8c9c6ad..644103a 100644
> --- a/arch/powerpc/include/asm/dma-mapping.h
> +++ b/arch/powerpc/include/asm/dma-mapping.h
> @@ -100,7 +100,7 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
>  static inline dma_addr_t get_dma_offset(struct device *dev)
>  {
>  	if (dev)
> -		return dev->archdata.dma_data.dma_offset;
> +		return dev->archdata.dma_offset;
>  
>  	return PCI_DRAM_OFFSET;
>  }
> @@ -108,7 +108,7 @@ static inline dma_addr_t get_dma_offset(struct device *dev)
>  static inline void set_dma_offset(struct device *dev, dma_addr_t off)
>  {
>  	if (dev)
> -		dev->archdata.dma_data.dma_offset = off;
> +		dev->archdata.dma_offset = off;
>  }
>  
>  /* this will be removed soon */
> diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
> index edfc980..0f605a4 100644
> --- a/arch/powerpc/include/asm/iommu.h
> +++ b/arch/powerpc/include/asm/iommu.h
> @@ -70,15 +70,17 @@ struct iommu_table {
>  
>  struct scatterlist;
>  
> +#ifdef CONFIG_PPC64
>  static inline void set_iommu_table_base(struct device *dev, void *base)
>  {
> -	dev->archdata.dma_data.iommu_table_base = base;
> +	dev->archdata.iommu_table_base = base;
>  }
>  
>  static inline void *get_iommu_table_base(struct device *dev)
>  {
> -	return dev->archdata.dma_data.iommu_table_base;
> +	return dev->archdata.iommu_table_base;
>  }
> +#endif
>  
>  /* Frees table for an individual device node */
>  extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);

^ permalink raw reply

* Re: [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2010-10-08 23:31 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.1010081102090.19518@localhost.localdomain>

On Fri, 2010-10-08 at 11:04 -0500, Kumar Gala wrote:
> Ben,
> 
> This isn't critical, but it does fix having the ppc64e_defconfig
> build cleanly.

BTW. Do you have a -next for me ? It's past time :-)

Cheers,
Ben.

> - k
> 
> The following changes since commit 6b0cd00bc396daf5c2dcf17a8d82055335341f46:
> 
>   Merge branch 'hwpoison-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6 (2010-10-07 13:59:32 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git merge
> 
> Kumar Gala (1):
>       powerpc/ppc64e: Fix link problem when building ppc64e_defconfig
> 
>  arch/powerpc/platforms/85xx/smp.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)

^ permalink raw reply

* Re: [PATCH 07/11] powerpc/fsl-booke: Add support for FSL 64-bit e5500 core
From: Scott Wood @ 2010-10-08 20:55 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1286564813-21209-7-git-send-email-galak@kernel.crashing.org>

On Fri, 8 Oct 2010 14:06:49 -0500
Kumar Gala <galak@kernel.crashing.org> wrote:

> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
> index d361f81..19083b3 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -132,13 +132,18 @@ config PPC_E500MC
>  	select PPC_FPU
>  	depends on E500
>  
> +config PPC_E5500
> +	bool
> +	select PPC_FPU
> +	select PPC_E500MC if PPC32

Currently E500MC implies E500.  With this, E5500 would not imply E500
-- hence all the ifdefs with E500 || E5500 that this adds.  When would
we want to ifdef E500 or E500MC but not E5500?

Given how similar e500mc and e5500 are, I think we should just use
CONFIG_E500MC for it.  Any 32/64-bit distinctions would just check
CONFIG_PPC64, CONFIG_BOOK3E_64, or similar.

-Scott

^ permalink raw reply


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