* Re: [v4,4/4] powernv: powerpc: Add winkle support for offline cpus
From: Michael Ellerman @ 2014-12-15 0:01 UTC (permalink / raw)
To: Shreyas B Prabhu; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <548D7A0E.2060107@linux.vnet.ibm.com>
On Sun, 2014-12-14 at 17:22 +0530, Shreyas B Prabhu wrote:
> On Sunday 14 December 2014 03:35 PM, Michael Ellerman wrote:
> >> diff --git a/arch/powerpc/platforms/powernv/subcore.h b/arch/powerpc/platforms/powernv/subcore.h
> >> index 148abc9..604eb40 100644
> >> --- a/arch/powerpc/platforms/powernv/subcore.h
> >> +++ b/arch/powerpc/platforms/powernv/subcore.h
> >> @@ -15,4 +15,5 @@
> >>
> >> #ifndef __ASSEMBLY__
> >> void split_core_secondary_loop(u8 *state);
> >> +extern void update_subcore_sibling_mask(void);
> >> #endif
> >
> > subcore.c isn't built for CONFIG_SMP=n, resulting in:
> >
> > setup.c:(.init.text+0x34b0): undefined reference to `.update_subcore_sibling_mask'
> >
> > I needed to add:
> >
> > +#else
> > +static inline void update_subcore_sibling_mask(void) { };
> > +#endif /* CONFIG_SMP */
> Sorry I missed that.
No worries.
Can you please do a quick test with a SMP=n kernel.
It looks like it should work, but it would be good to test.
cheers
^ permalink raw reply
* Re: [PATCH 13/18] powerpc/uaccess: fix sparse errors
From: Benjamin Herrenschmidt @ 2014-12-15 0:05 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: linux-arch, Arnd Bergmann, linux-kernel, Paul Mackerras,
linuxppc-dev
In-Reply-To: <1418575877-21488-14-git-send-email-mst@redhat.com>
On Sun, 2014-12-14 at 18:52 +0200, Michael S. Tsirkin wrote:
> virtio wants to read bitwise types from userspace using get_user. At the
> moment this triggers sparse errors, since the value is passed through an
> integer.
>
> Fix that up using __force.
You mean bitfields ? Argh ... we should just remove them from the
compiler and be done with it :-(
Ben.
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> arch/powerpc/include/asm/uaccess.h | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
> index 9485b43..a0c071d 100644
> --- a/arch/powerpc/include/asm/uaccess.h
> +++ b/arch/powerpc/include/asm/uaccess.h
> @@ -284,7 +284,7 @@ do { \
> if (!is_kernel_addr((unsigned long)__gu_addr)) \
> might_fault(); \
> __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
> - (x) = (__typeof__(*(ptr)))__gu_val; \
> + (x) = (__force __typeof__(*(ptr)))__gu_val; \
> __gu_err; \
> })
> #endif /* __powerpc64__ */
> @@ -297,7 +297,7 @@ do { \
> might_fault(); \
> if (access_ok(VERIFY_READ, __gu_addr, (size))) \
> __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
> - (x) = (__typeof__(*(ptr)))__gu_val; \
> + (x) = (__force __typeof__(*(ptr)))__gu_val; \
> __gu_err; \
> })
>
> @@ -308,7 +308,7 @@ do { \
> const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
> __chk_user_ptr(ptr); \
> __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
> - (x) = (__typeof__(*(ptr)))__gu_val; \
> + (x) = (__force __typeof__(*(ptr)))__gu_val; \
> __gu_err; \
> })
>
^ permalink raw reply
* Re: [PATCH] powerpc/pci: remove the multi-init for pci_dn->phb
From: Wei Yang @ 2014-12-15 1:35 UTC (permalink / raw)
To: Gavin Shan; +Cc: Wei Yang, linuxppc-dev
In-Reply-To: <20141214105742.GA4476@shangw>
On Sun, Dec 14, 2014 at 09:57:42PM +1100, Gavin Shan wrote:
>On Sat, Dec 13, 2014 at 11:09:04AM +0800, Wei Yang wrote:
>>pci_dn->phb is set to phb in update_dn_pci_info(), if succeed.
>>
>>This patch removes the duplication of pci_dn->phb initialization.
>>
>>Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com>
>>---
>> arch/powerpc/kernel/pci_dn.c | 1 -
>> 1 file changed, 1 deletion(-)
>>
>>diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
>>index ddae246..d40b579 100644
>>--- a/arch/powerpc/kernel/pci_dn.c
>>+++ b/arch/powerpc/kernel/pci_dn.c
>>@@ -382,7 +382,6 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)
>> pdn = dn->data;
>> if (pdn) {
>> pdn->devfn = pdn->busno = -1;
>>- pdn->phb = phb;
>> phb->firmware_data = pdn;
>
>It seems the patch bases on unmerged code because "phb->firmware_data"
>isn't existing yet in upstream or ppc.next.
>
Oh, my mistake. I will rebase it on the latest upstream.
>Thanks,
>Gavin
>
>> }
>>
>>--
>>1.7.9.5
>>
>>_______________________________________________
>>Linuxppc-dev mailing list
>>Linuxppc-dev@lists.ozlabs.org
>>https://lists.ozlabs.org/listinfo/linuxppc-dev
--
Richard Yang
Help you, Help me
^ permalink raw reply
* Re: [PATCH 13/18] powerpc/uaccess: fix sparse errors
From: Benjamin Herrenschmidt @ 2014-12-15 1:37 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: linux-arch, Arnd Bergmann, linux-kernel, Paul Mackerras,
linuxppc-dev
In-Reply-To: <1418601906.5111.37.camel@kernel.crashing.org>
On Mon, 2014-12-15 at 11:05 +1100, Benjamin Herrenschmidt wrote:
> On Sun, 2014-12-14 at 18:52 +0200, Michael S. Tsirkin wrote:
> > virtio wants to read bitwise types from userspace using get_user. At the
> > moment this triggers sparse errors, since the value is passed through an
> > integer.
> >
> > Fix that up using __force.
>
> You mean bitfields ? Argh ... we should just remove them from the
> compiler and be done with it :-(
Oh... no I suppose you actually meant explicit endian fields, ie, __be32
or __le32 right ? Ack on that. It sucks a bit but I think it's
acceptable.
Cheers,
Ben.
> Ben.
>
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> > arch/powerpc/include/asm/uaccess.h | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
> > index 9485b43..a0c071d 100644
> > --- a/arch/powerpc/include/asm/uaccess.h
> > +++ b/arch/powerpc/include/asm/uaccess.h
> > @@ -284,7 +284,7 @@ do { \
> > if (!is_kernel_addr((unsigned long)__gu_addr)) \
> > might_fault(); \
> > __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
> > - (x) = (__typeof__(*(ptr)))__gu_val; \
> > + (x) = (__force __typeof__(*(ptr)))__gu_val; \
> > __gu_err; \
> > })
> > #endif /* __powerpc64__ */
> > @@ -297,7 +297,7 @@ do { \
> > might_fault(); \
> > if (access_ok(VERIFY_READ, __gu_addr, (size))) \
> > __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
> > - (x) = (__typeof__(*(ptr)))__gu_val; \
> > + (x) = (__force __typeof__(*(ptr)))__gu_val; \
> > __gu_err; \
> > })
> >
> > @@ -308,7 +308,7 @@ do { \
> > const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
> > __chk_user_ptr(ptr); \
> > __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
> > - (x) = (__typeof__(*(ptr)))__gu_val; \
> > + (x) = (__force __typeof__(*(ptr)))__gu_val; \
> > __gu_err; \
> > })
> >
>
^ permalink raw reply
* [PATCH V2] powerpc/pci: remove the multi-init for pci_dn->phb
From: Wei Yang @ 2014-12-15 1:45 UTC (permalink / raw)
To: gwshan, linuxppc-dev; +Cc: Wei Yang
In-Reply-To: <20141214105742.GA4476@shangw>
pci_dn->phb is set to phb in update_dn_pci_info(), if succeed.
This patch removes the duplication of pci_dn->phb initialization.
Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com>
V2:
* rebase the code on v3.18
---
arch/powerpc/kernel/pci_dn.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 1f61fab..83df307 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -147,10 +147,8 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)
/* PHB nodes themselves must not match */
update_dn_pci_info(dn, phb);
pdn = dn->data;
- if (pdn) {
+ if (pdn)
pdn->devfn = pdn->busno = -1;
- pdn->phb = phb;
- }
/* Update dn->phb ptrs for new phb and children devices */
traverse_pci_devices(dn, update_dn_pci_info, phb);
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] powerpc/kernel: Make syscall_exit a local label
From: Michael Ellerman @ 2014-12-15 3:03 UTC (permalink / raw)
To: David Laight; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1CA03452@AcuExch.aculab.com>
On Fri, 2014-12-05 at 10:27 +0000, David Laight wrote:
> From: Michael Ellerman
> > diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
> > index 0905c8da90f1..d8828e50dbef 100644
> > --- a/arch/powerpc/kernel/entry_64.S
> > +++ b/arch/powerpc/kernel/entry_64.S
> > @@ -178,7 +178,7 @@ system_call: /* label this so stack traces look sane */
> > mtctr r12
> > bctrl /* Call handler */
>
> Why not add a 'nop' here instead?
Because we'd rather not add extra instructions to the syscall path unless we
really need to. A local label seems like the preferable solution to me.
cheers
^ permalink raw reply
* Re: [PATCH V2] powerpc/pci: remove the multi-init for pci_dn->phb
From: Gavin Shan @ 2014-12-15 3:15 UTC (permalink / raw)
To: Wei Yang; +Cc: linuxppc-dev, gwshan
In-Reply-To: <1418607900-7960-1-git-send-email-weiyang@linux.vnet.ibm.com>
On Mon, Dec 15, 2014 at 09:45:00AM +0800, Wei Yang wrote:
>pci_dn->phb is set to phb in update_dn_pci_info(), if succeed.
>
>This patch removes the duplication of pci_dn->phb initialization.
>
>Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Thanks,
Gavin
>
>V2:
> * rebase the code on v3.18
>---
> arch/powerpc/kernel/pci_dn.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
>diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
>index 1f61fab..83df307 100644
>--- a/arch/powerpc/kernel/pci_dn.c
>+++ b/arch/powerpc/kernel/pci_dn.c
>@@ -147,10 +147,8 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)
> /* PHB nodes themselves must not match */
> update_dn_pci_info(dn, phb);
> pdn = dn->data;
>- if (pdn) {
>+ if (pdn)
> pdn->devfn = pdn->busno = -1;
>- pdn->phb = phb;
>- }
>
> /* Update dn->phb ptrs for new phb and children devices */
> traverse_pci_devices(dn, update_dn_pci_info, phb);
>--
>1.7.9.5
>
^ permalink raw reply
* Re: [PATCH 7/7] CXL: Unmap MMIO regions when detaching a context
From: Ian Munsie @ 2014-12-15 3:32 UTC (permalink / raw)
To: mpe
Cc: cbe-oss-dev, Philippe Bergheaud, mikey, Aneesh Kumar K.V,
linux-kernel, linuxppc-dev, anton, jk
In-Reply-To: <1418026681-14787-7-git-send-email-imunsie@au.ibm.com>
Excerpts from Ian Munsie's message of 2014-12-08 19:18:01 +1100:
> From: Ian Munsie <imunsie@au1.ibm.com>
>
> If we need to force detach a context (e.g. due to EEH or simply force
> unbinding the driver) we should prevent the userspace contexts from
> being able to access the Problem State Area MMIO region further, which
> they may have mapped with mmap().
>
> This patch unmaps any mapped MMIO regions when detaching a userspace
> context.
Might want to drop this one for now - Philippe found that it sometimes
causes an issue when multiple contexts are using the afu. Seems that
unmap_mapping_range() unmapped a bit more than I expected.
Cheers,
-Ian
^ permalink raw reply
* [PATCH v5] dmaengine: Driver support for FSL RaidEngine device.
From: xuelin.shi @ 2014-12-15 2:32 UTC (permalink / raw)
To: dan.j.williams, vinod.koul
Cc: dmaengine, Harninder Rai, Xuelin Shi, linuxppc-dev, Naveen Burmi
From: Xuelin Shi <xuelin.shi@freescale.com>
The RaidEngine is a new FSL hardware used for Raid5/6 acceration.
This patch enables the RaidEngine functionality and provides
hardware offloading capability for memcpy, xor and pq computation.
It works with async_tx.
Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
Signed-off-by: Xuelin Shi <xuelin.shi@freescale.com>
---
changes for v5:
- align symbol to fsl_re_xxx to avoid namespace issue.
- switch back to tasklet
- add xor/pq continuation in to support more than 16 srcs.
drivers/dma/Kconfig | 11 +
drivers/dma/Makefile | 1 +
drivers/dma/fsl_raid.c | 889 +++++++++++++++++++++++++++++++++++++++++++++++++
drivers/dma/fsl_raid.h | 306 +++++++++++++++++
4 files changed, 1207 insertions(+)
create mode 100644 drivers/dma/fsl_raid.c
create mode 100644 drivers/dma/fsl_raid.h
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index f2b2c4e..37397cd 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -125,6 +125,17 @@ config FSL_DMA
EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
some Txxx and Bxxx parts.
+config FSL_RAID
+ tristate "Freescale RAID engine Support"
+ depends on FSL_SOC && !ASYNC_TX_ENABLE_CHANNEL_SWITCH
+ select DMA_ENGINE
+ select DMA_ENGINE_RAID
+ ---help---
+ Enable support for Freescale RAID Engine. RAID Engine is
+ available on some QorIQ SoCs (like P5020/P5040). It has
+ the capability to offload memcpy, xor and pq computation
+ for raid5/6.
+
config MPC512X_DMA
tristate "Freescale MPC512x built-in DMA engine support"
depends on PPC_MPC512x || PPC_MPC831x
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 2022b54..b3f8d9e 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
obj-$(CONFIG_TI_CPPI41) += cppi41.o
obj-$(CONFIG_K3_DMA) += k3dma.o
obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
+obj-$(CONFIG_FSL_RAID) += fsl_raid.o
obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o
obj-y += xilinx/
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
new file mode 100644
index 0000000..ef311fd
--- /dev/null
+++ b/drivers/dma/fsl_raid.c
@@ -0,0 +1,889 @@
+/*
+ * drivers/dma/fsl_raid.c
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ * Harninder Rai <harninder.rai@freescale.com>
+ * Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Rewrite:
+ * Xuelin Shi <xuelin.shi@freescale.com>
+ *
+ * Copyright (c) 2010-2014 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Theory of operation:
+ *
+ * General capabilities:
+ * RAID Engine (RE) block is capable of offloading XOR, memcpy and P/Q
+ * calculations required in RAID5 and RAID6 operations. RE driver
+ * registers with Linux's ASYNC layer as dma driver. RE hardware
+ * maintains strict ordering of the requests through chained
+ * command queueing.
+ *
+ * Data flow:
+ * Software RAID layer of Linux (MD layer) maintains RAID partitions,
+ * strips, stripes etc. It sends requests to the underlying ASYNC layer
+ * which further passes it to RE driver. ASYNC layer decides which request
+ * goes to which job ring of RE hardware. For every request processed by
+ * RAID Engine, driver gets an interrupt unless coalescing is set. The
+ * per job ring interrupt handler checks the status register for errors,
+ * clears the interrupt and leave the post interrupt processing to the irq
+ * thread.
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include "dmaengine.h"
+#include "fsl_raid.h"
+
+#define FSL_RE_MAX_XOR_SRCS 16
+#define FSL_RE_MAX_PQ_SRCS 16
+#define FSL_RE_MIN_DESCS 256
+#define FSL_RE_MAX_DESCS (4 * FSL_RE_MIN_DESCS)
+#define FSL_RE_FRAME_FORMAT 0x1
+#define FSL_RE_MAX_DATA_LEN (1024*1024)
+
+#define to_fsl_re_dma_desc(tx) container_of(tx, struct fsl_re_desc, async_tx)
+
+/* Add descriptors into per chan software queue - submit_q */
+static dma_cookie_t fsl_re_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct fsl_re_desc *desc;
+ struct fsl_re_chan *re_chan;
+ dma_cookie_t cookie;
+ unsigned long flags;
+
+ desc = to_fsl_re_dma_desc(tx);
+ re_chan = container_of(tx->chan, struct fsl_re_chan, chan);
+
+ spin_lock_irqsave(&re_chan->desc_lock, flags);
+ cookie = dma_cookie_assign(tx);
+ list_add_tail(&desc->node, &re_chan->submit_q);
+ spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+
+ return cookie;
+}
+
+/* Copy descriptor from per chan software queue into hardware job ring */
+static void fsl_re_issue_pending(struct dma_chan *chan)
+{
+ struct fsl_re_chan *re_chan;
+ int avail;
+ struct fsl_re_desc *desc, *_desc;
+ unsigned long flags;
+
+ re_chan = container_of(chan, struct fsl_re_chan, chan);
+
+ spin_lock_irqsave(&re_chan->desc_lock, flags);
+ avail = FSL_RE_SLOT_AVAIL(
+ in_be32(&re_chan->jrregs->inbring_slot_avail));
+
+ list_for_each_entry_safe(desc, _desc, &re_chan->submit_q, node) {
+ if (!avail)
+ break;
+
+ list_move_tail(&desc->node, &re_chan->active_q);
+
+ memcpy(&re_chan->inb_ring_virt_addr[re_chan->inb_count],
+ &desc->hwdesc, sizeof(struct fsl_re_hw_desc));
+
+ re_chan->inb_count = (re_chan->inb_count + 1) &
+ FSL_RE_RING_SIZE_MASK;
+ out_be32(&re_chan->jrregs->inbring_add_job, FSL_RE_ADD_JOB(1));
+ avail--;
+ }
+ spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+}
+
+static void fsl_re_desc_done(struct fsl_re_desc *desc)
+{
+ dma_async_tx_callback callback;
+ void *callback_param;
+
+ dma_cookie_complete(&desc->async_tx);
+
+ callback = desc->async_tx.callback;
+ callback_param = desc->async_tx.callback_param;
+ if (callback)
+ callback(callback_param);
+
+ dma_descriptor_unmap(&desc->async_tx);
+}
+
+static void fsl_re_cleanup_descs(struct fsl_re_chan *re_chan)
+{
+ struct fsl_re_desc *desc, *_desc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&re_chan->desc_lock, flags);
+ list_for_each_entry_safe(desc, _desc, &re_chan->ack_q, node) {
+ if (async_tx_test_ack(&desc->async_tx))
+ list_move_tail(&desc->node, &re_chan->free_q);
+ }
+ spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+
+ fsl_re_issue_pending(&re_chan->chan);
+}
+
+static void fsl_re_dequeue(unsigned long data)
+{
+ struct fsl_re_chan *re_chan;
+ struct fsl_re_desc *desc, *_desc;
+ struct fsl_re_hw_desc *hwdesc;
+ unsigned long flags;
+ unsigned int count, oub_count;
+ int found;
+
+ re_chan = dev_get_drvdata((struct device *)data);
+
+ fsl_re_cleanup_descs(re_chan);
+
+ spin_lock_irqsave(&re_chan->desc_lock, flags);
+ count = FSL_RE_SLOT_FULL(in_be32(&re_chan->jrregs->oubring_slot_full));
+ while (count--) {
+ found = 0;
+ hwdesc = &re_chan->oub_ring_virt_addr[re_chan->oub_count];
+ list_for_each_entry_safe(desc, _desc, &re_chan->active_q,
+ node) {
+ /* compare the hw dma addr to find the completed */
+ if (desc->hwdesc.lbea32 == hwdesc->lbea32 &&
+ desc->hwdesc.addr_low == hwdesc->addr_low) {
+ found = 1;
+ break;
+ }
+ }
+
+ BUG_ON(!found);
+ fsl_re_desc_done(desc);
+ list_move_tail(&desc->node, &re_chan->ack_q);
+
+ oub_count = (re_chan->oub_count + 1) & FSL_RE_RING_SIZE_MASK;
+ re_chan->oub_count = oub_count;
+
+ out_be32(&re_chan->jrregs->oubring_job_rmvd,
+ FSL_RE_RMVD_JOB(1));
+ }
+ spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+}
+
+/* Per Job Ring interrupt handler */
+static irqreturn_t fsl_re_isr(int irq, void *data)
+{
+ struct fsl_re_chan *re_chan;
+ u32 irqstate, status;
+
+ re_chan = dev_get_drvdata((struct device *)data);
+
+ irqstate = in_be32(&re_chan->jrregs->jr_interrupt_status);
+ if (!irqstate)
+ return IRQ_NONE;
+
+ /*
+ * There's no way in upper layer (read MD layer) to recover from
+ * error conditions except restart everything. In long term we
+ * need to do something more than just crashing
+ */
+ if (irqstate & FSL_RE_ERROR) {
+ status = in_be32(&re_chan->jrregs->jr_status);
+ dev_err(re_chan->dev, "chan error irqstate: %x, status: %x\n",
+ irqstate, status);
+ }
+
+ /* Clear interrupt */
+ out_be32(&re_chan->jrregs->jr_interrupt_status, FSL_RE_CLR_INTR);
+
+ tasklet_schedule(&re_chan->irqtask);
+
+ return IRQ_HANDLED;
+}
+
+static enum dma_status fsl_re_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ return dma_cookie_status(chan, cookie, txstate);
+}
+
+static void fill_cfd_frame(struct fsl_re_cmpnd_frame *cf, u8 index,
+ size_t length, dma_addr_t addr, bool final)
+{
+ u32 efrl = length & FSL_RE_CF_LENGTH_MASK;
+
+ efrl |= final << FSL_RE_CF_FINAL_SHIFT;
+ cf[index].efrl32 = efrl;
+ cf[index].addr_high = upper_32_bits(addr);
+ cf[index].addr_low = lower_32_bits(addr);
+}
+
+static struct fsl_re_desc *fsl_re_init_desc(struct fsl_re_chan *re_chan,
+ struct fsl_re_desc *desc,
+ void *cf, dma_addr_t paddr)
+{
+ desc->re_chan = re_chan;
+ desc->async_tx.tx_submit = fsl_re_tx_submit;
+ dma_async_tx_descriptor_init(&desc->async_tx, &re_chan->chan);
+ INIT_LIST_HEAD(&desc->node);
+
+ desc->hwdesc.fmt32 = FSL_RE_FRAME_FORMAT << FSL_RE_HWDESC_FMT_SHIFT;
+ desc->hwdesc.lbea32 = upper_32_bits(paddr);
+ desc->hwdesc.addr_low = lower_32_bits(paddr);
+ desc->cf_addr = cf;
+ desc->cf_paddr = paddr;
+
+ desc->cdb_addr = (void *)(cf + FSL_RE_CF_DESC_SIZE);
+ desc->cdb_paddr = paddr + FSL_RE_CF_DESC_SIZE;
+
+ return desc;
+}
+
+static struct fsl_re_desc *fsl_re_chan_alloc_desc(struct fsl_re_chan *re_chan,
+ unsigned long flags)
+{
+ struct fsl_re_desc *desc = NULL;
+ void *cf;
+ dma_addr_t paddr;
+ unsigned long lock_flag;
+
+ fsl_re_cleanup_descs(re_chan);
+
+ spin_lock_irqsave(&re_chan->desc_lock, lock_flag);
+ if (!list_empty(&re_chan->free_q)) {
+ /* take one desc from free_q */
+ desc = list_first_entry(&re_chan->free_q,
+ struct fsl_re_desc, node);
+ list_del(&desc->node);
+
+ desc->async_tx.flags = flags;
+ }
+ spin_unlock_irqrestore(&re_chan->desc_lock, lock_flag);
+
+ if (!desc) {
+ desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+ cf = dma_pool_alloc(re_chan->re_dev->cf_desc_pool, GFP_NOWAIT,
+ &paddr);
+ if (!desc || !cf) {
+ kfree(desc);
+ return NULL;
+ }
+
+ desc = fsl_re_init_desc(re_chan, desc, cf, paddr);
+ desc->async_tx.flags = flags;
+
+ spin_lock_irqsave(&re_chan->desc_lock, lock_flag);
+ re_chan->alloc_count++;
+ spin_unlock_irqrestore(&re_chan->desc_lock, lock_flag);
+ }
+
+ return desc;
+}
+
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_genq(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, const unsigned char *scf, size_t len,
+ unsigned long flags)
+{
+ struct fsl_re_chan *re_chan;
+ struct fsl_re_desc *desc;
+ struct fsl_re_xor_cdb *xor;
+ struct fsl_re_cmpnd_frame *cf;
+ u32 cdb;
+ unsigned int i, j;
+ unsigned int save_src_cnt = src_cnt;
+ int cont_q = 0;
+
+ if (len > FSL_RE_MAX_DATA_LEN) {
+ pr_err("Length greater than %d not supported\n",
+ FSL_RE_MAX_DATA_LEN);
+ return NULL;
+ }
+
+ re_chan = container_of(chan, struct fsl_re_chan, chan);
+ desc = fsl_re_chan_alloc_desc(re_chan, flags);
+ if (desc <= 0)
+ return NULL;
+
+ if (scf && (flags & DMA_PREP_CONTINUE)) {
+ cont_q = 1;
+ src_cnt += 1;
+ }
+
+ /* Filling xor CDB */
+ cdb = FSL_RE_XOR_OPCODE << FSL_RE_CDB_OPCODE_SHIFT;
+ cdb |= (src_cnt - 1) << FSL_RE_CDB_NRCS_SHIFT;
+ cdb |= FSL_RE_BLOCK_SIZE << FSL_RE_CDB_BLKSIZE_SHIFT;
+ cdb |= FSL_RE_INTR_ON_ERROR << FSL_RE_CDB_ERROR_SHIFT;
+ cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT;
+ xor = desc->cdb_addr;
+ xor->cdb32 = cdb;
+
+ if (scf) {
+ /* compute q = src0*coef0^src1*coef1^..., * is GF(8) mult */
+ for (i = 0; i < save_src_cnt; i++)
+ xor->gfm[i] = scf[i];
+ if (cont_q)
+ xor->gfm[i++] = 1;
+ } else {
+ /* compute P, that is XOR all srcs */
+ for (i = 0; i < src_cnt; i++)
+ xor->gfm[i] = 1;
+ }
+
+ /* Filling frame 0 of compound frame descriptor with CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, sizeof(*xor), desc->cdb_paddr, 0);
+
+ /* Fill CFD's 1st frame with dest buffer */
+ fill_cfd_frame(cf, 1, len, dest, 0);
+
+ /* Fill CFD's rest of the frames with source buffers */
+ for (i = 2, j = 0; j < save_src_cnt; i++, j++)
+ fill_cfd_frame(cf, i, len, src[j], 0);
+
+ if (cont_q)
+ fill_cfd_frame(cf, i++, len, dest, 0);
+
+ /* Setting the final bit in the last source buffer frame in CFD */
+ cf[i - 1].efrl32 |= 1 << FSL_RE_CF_FINAL_SHIFT;
+
+ return &desc->async_tx;
+}
+
+/*
+ * Prep function for P parity calculation.In RAID Engine terminology,
+ * XOR calculation is called GenQ calculation done through GenQ command
+ */
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_xor(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, size_t len, unsigned long flags)
+{
+ /* NULL let genq take all coef as 1 */
+ return fsl_re_prep_dma_genq(chan, dest, src, src_cnt, NULL, len, flags);
+}
+
+/*
+ * Prep function for P/Q parity calculation.In RAID Engine terminology,
+ * P/Q calculation is called GenQQ done through GenQQ command
+ */
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_pq(
+ struct dma_chan *chan, dma_addr_t *dest, dma_addr_t *src,
+ unsigned int src_cnt, const unsigned char *scf, size_t len,
+ unsigned long flags)
+{
+ struct fsl_re_chan *re_chan;
+ struct fsl_re_desc *desc;
+ struct fsl_re_pq_cdb *pq;
+ struct fsl_re_cmpnd_frame *cf;
+ u32 cdb;
+ u8 *p;
+ int gfmq_len, i, j;
+ unsigned int save_src_cnt = src_cnt;
+
+ if (len > FSL_RE_MAX_DATA_LEN) {
+ pr_err("Length greater than %d not supported\n",
+ FSL_RE_MAX_DATA_LEN);
+ return NULL;
+ }
+
+ /*
+ * RE requires at least 2 sources, if given only one source, we pass the
+ * second source same as the first one.
+ * With only one source, generating P is meaningless, only generate Q.
+ */
+ if (src_cnt == 1) {
+ struct dma_async_tx_descriptor *tx;
+ dma_addr_t dma_src[2];
+ unsigned char coef[2];
+
+ dma_src[0] = *src;
+ coef[0] = *scf;
+ dma_src[1] = *src;
+ coef[1] = 0;
+ tx = fsl_re_prep_dma_genq(chan, dest[1], dma_src, 2, coef, len,
+ flags);
+ if (tx)
+ desc = to_fsl_re_dma_desc(tx);
+
+ return tx;
+ }
+
+ /*
+ * During RAID6 array creation, Linux's MD layer gets P and Q
+ * calculated separately in two steps. But our RAID Engine has
+ * the capability to calculate both P and Q with a single command
+ * Hence to merge well with MD layer, we need to provide a hook
+ * here and call re_jq_prep_dma_genq() function
+ */
+
+ if (flags & DMA_PREP_PQ_DISABLE_P)
+ return fsl_re_prep_dma_genq(chan, dest[1], src, src_cnt,
+ scf, len, flags);
+
+ if (flags & DMA_PREP_CONTINUE)
+ src_cnt += 3;
+
+ re_chan = container_of(chan, struct fsl_re_chan, chan);
+ desc = fsl_re_chan_alloc_desc(re_chan, flags);
+ if (desc <= 0)
+ return NULL;
+
+ /* Filling GenQQ CDB */
+ cdb = FSL_RE_PQ_OPCODE << FSL_RE_CDB_OPCODE_SHIFT;
+ cdb |= (src_cnt - 1) << FSL_RE_CDB_NRCS_SHIFT;
+ cdb |= FSL_RE_BLOCK_SIZE << FSL_RE_CDB_BLKSIZE_SHIFT;
+ cdb |= FSL_RE_BUFFER_OUTPUT << FSL_RE_CDB_BUFFER_SHIFT;
+ cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT;
+
+ pq = desc->cdb_addr;
+ pq->cdb32 = cdb;
+
+ p = pq->gfm_q1;
+ /* Init gfm_q1[] */
+ for (i = 0; i < src_cnt; i++)
+ p[i] = 1;
+
+ /* Align gfm[] to 32bit */
+ gfmq_len = ALIGN(src_cnt, 4);
+
+ /* Init gfm_q2[] */
+ p += gfmq_len;
+ for (i = 0; i < src_cnt; i++)
+ p[i] = scf[i];
+
+ /* Filling frame 0 of compound frame descriptor with CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, sizeof(struct fsl_re_pq_cdb), desc->cdb_paddr, 0);
+
+ /* Fill CFD's 1st & 2nd frame with dest buffers */
+ for (i = 1, j = 0; i < 3; i++, j++)
+ fill_cfd_frame(cf, i, len, dest[j], 0);
+
+ /* Fill CFD's rest of the frames with source buffers */
+ for (i = 3, j = 0; j < save_src_cnt; i++, j++)
+ fill_cfd_frame(cf, i, len, src[j], 0);
+
+ /* PQ computation continuation */
+ if (flags & DMA_PREP_CONTINUE) {
+ BUG_ON(src_cnt - save_src_cnt != 3);
+ p[save_src_cnt] = 0;
+ p[save_src_cnt + 1] = 0;
+ p[save_src_cnt + 2] = 1;
+ fill_cfd_frame(cf, i++, len, dest[0], 0);
+ fill_cfd_frame(cf, i++, len, dest[1], 0);
+ fill_cfd_frame(cf, i++, len, dest[1], 0);
+ }
+
+ /* Setting the final bit in the last source buffer frame in CFD */
+ cf[i - 1].efrl32 |= 1 << FSL_RE_CF_FINAL_SHIFT;
+
+ return &desc->async_tx;
+}
+
+/*
+ * Prep function for memcpy. In RAID Engine, memcpy is done through MOVE
+ * command. Logic of this function will need to be modified once multipage
+ * support is added in Linux's MD/ASYNC Layer
+ */
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_memcpy(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct fsl_re_chan *re_chan;
+ struct fsl_re_desc *desc;
+ size_t length;
+ struct fsl_re_cmpnd_frame *cf;
+ struct fsl_re_move_cdb *move;
+ u32 cdb;
+
+ re_chan = container_of(chan, struct fsl_re_chan, chan);
+
+ if (len > FSL_RE_MAX_DATA_LEN) {
+ pr_err("Length greater than %d not supported\n",
+ FSL_RE_MAX_DATA_LEN);
+ return NULL;
+ }
+
+ desc = fsl_re_chan_alloc_desc(re_chan, flags);
+ if (desc <= 0)
+ return NULL;
+
+ /* Filling move CDB */
+ cdb = FSL_RE_MOVE_OPCODE << FSL_RE_CDB_OPCODE_SHIFT;
+ cdb |= FSL_RE_BLOCK_SIZE << FSL_RE_CDB_BLKSIZE_SHIFT;
+ cdb |= FSL_RE_INTR_ON_ERROR << FSL_RE_CDB_ERROR_SHIFT;
+ cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT;
+
+ move = desc->cdb_addr;
+ move->cdb32 = cdb;
+
+ /* Filling frame 0 of CFD with move CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, sizeof(*move), desc->cdb_paddr, 0);
+
+ length = min_t(size_t, len, FSL_RE_MAX_DATA_LEN);
+
+ /* Fill CFD's 1st frame with dest buffer */
+ fill_cfd_frame(cf, 1, length, dest, 0);
+
+ /* Fill CFD's 2nd frame with src buffer */
+ fill_cfd_frame(cf, 2, length, src, 1);
+
+ return &desc->async_tx;
+}
+
+static int fsl_re_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct fsl_re_chan *re_chan;
+ struct fsl_re_desc *desc;
+ void *cf;
+ dma_addr_t paddr;
+ int i;
+
+ re_chan = container_of(chan, struct fsl_re_chan, chan);
+ for (i = 0; i < FSL_RE_MIN_DESCS; i++) {
+ desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+ cf = dma_pool_alloc(re_chan->re_dev->cf_desc_pool, GFP_KERNEL,
+ &paddr);
+ if (!desc || !cf) {
+ kfree(desc);
+ break;
+ }
+
+ INIT_LIST_HEAD(&desc->node);
+ fsl_re_init_desc(re_chan, desc, cf, paddr);
+
+ list_add_tail(&desc->node, &re_chan->free_q);
+ re_chan->alloc_count++;
+ }
+ return re_chan->alloc_count;
+}
+
+static void fsl_re_free_chan_resources(struct dma_chan *chan)
+{
+ struct fsl_re_chan *re_chan;
+ struct fsl_re_desc *desc;
+
+ re_chan = container_of(chan, struct fsl_re_chan, chan);
+ while (re_chan->alloc_count--) {
+ desc = list_first_entry(&re_chan->free_q,
+ struct fsl_re_desc,
+ node);
+
+ list_del(&desc->node);
+ dma_pool_free(re_chan->re_dev->cf_desc_pool, desc->cf_addr,
+ desc->cf_paddr);
+ kfree(desc);
+ }
+
+ BUG_ON(!list_empty(&re_chan->free_q));
+}
+
+int fsl_re_chan_probe(struct platform_device *ofdev,
+ struct device_node *np, u8 q, u32 off)
+{
+ struct device *dev, *chandev;
+ struct fsl_re_drv_private *re_priv;
+ struct fsl_re_chan *chan;
+ struct dma_device *dma_dev;
+ u32 ptr;
+ u32 status;
+ int ret = 0, rc;
+ struct platform_device *chan_ofdev;
+
+ dev = &ofdev->dev;
+ re_priv = dev_get_drvdata(dev);
+ dma_dev = &re_priv->dma_dev;
+
+ chan = devm_kzalloc(dev, sizeof(*chan), GFP_KERNEL);
+ if (!chan)
+ return -ENOMEM;
+
+ /* create platform device for chan node */
+ chan_ofdev = of_platform_device_create(np, NULL, dev);
+ if (!chan_ofdev) {
+ dev_err(dev, "Not able to create ofdev for jr %d\n", q);
+ ret = -EINVAL;
+ goto err_free;
+ }
+
+ /* read reg property from dts */
+ rc = of_property_read_u32(np, "reg", &ptr);
+ if (rc) {
+ dev_err(dev, "Reg property not found in jr %d\n", q);
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ chan->jrregs = (struct fsl_re_chan_cfg *)((u8 *)re_priv->re_regs +
+ off + ptr);
+
+ /* read irq property from dts */
+ chan->irq = irq_of_parse_and_map(np, 0);
+ if (chan->irq == NO_IRQ) {
+ dev_err(dev, "No IRQ defined for JR %d\n", q);
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ snprintf(chan->name, sizeof(chan->name), "re_jr%02d", q);
+
+ chandev = &chan_ofdev->dev;
+ tasklet_init(&chan->irqtask, fsl_re_dequeue, (unsigned long)chandev);
+
+ ret = request_irq(chan->irq, fsl_re_isr, 0, chan->name, chandev);
+ if (ret) {
+ dev_err(dev, "Unable to register interrupt for JR %d\n", q);
+ ret = -EINVAL;
+ goto err_free;
+ }
+
+ re_priv->re_jrs[q] = chan;
+ chan->chan.device = dma_dev;
+ chan->chan.private = chan;
+ chan->dev = chandev;
+ chan->re_dev = re_priv;
+
+ spin_lock_init(&chan->desc_lock);
+ INIT_LIST_HEAD(&chan->ack_q);
+ INIT_LIST_HEAD(&chan->active_q);
+ INIT_LIST_HEAD(&chan->submit_q);
+ INIT_LIST_HEAD(&chan->free_q);
+
+ chan->inb_ring_virt_addr = dma_pool_alloc(chan->re_dev->hw_desc_pool,
+ GFP_KERNEL, &chan->inb_phys_addr);
+ if (!chan->inb_ring_virt_addr) {
+ dev_err(dev, "No dma memory for inb_ring_virt_addr\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ chan->oub_ring_virt_addr = dma_pool_alloc(chan->re_dev->hw_desc_pool,
+ GFP_KERNEL, &chan->oub_phys_addr);
+ if (!chan->oub_ring_virt_addr) {
+ dev_err(dev, "No dma memory for oub_ring_virt_addr\n");
+ ret = -ENOMEM;
+ goto err_free_1;
+ }
+
+ /* Program the Inbound/Outbound ring base addresses and size */
+ out_be32(&chan->jrregs->inbring_base_h,
+ chan->inb_phys_addr & FSL_RE_ADDR_BIT_MASK);
+ out_be32(&chan->jrregs->oubring_base_h,
+ chan->oub_phys_addr & FSL_RE_ADDR_BIT_MASK);
+ out_be32(&chan->jrregs->inbring_base_l,
+ chan->inb_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
+ out_be32(&chan->jrregs->oubring_base_l,
+ chan->oub_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
+ out_be32(&chan->jrregs->inbring_size,
+ FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
+ out_be32(&chan->jrregs->oubring_size,
+ FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
+
+ /* Read LIODN value from u-boot */
+ status = in_be32(&chan->jrregs->jr_config_1) & FSL_RE_REG_LIODN_MASK;
+
+ /* Program the CFG reg */
+ out_be32(&chan->jrregs->jr_config_1,
+ FSL_RE_CFG1_CBSI | FSL_RE_CFG1_CBS0 | status);
+
+ dev_set_drvdata(chandev, chan);
+
+ /* Enable RE/CHAN */
+ out_be32(&chan->jrregs->jr_command, FSL_RE_ENABLE);
+
+ return 0;
+
+err_free_1:
+ dma_pool_free(chan->re_dev->hw_desc_pool, chan->inb_ring_virt_addr,
+ chan->inb_phys_addr);
+err_free:
+ return ret;
+}
+
+/* Probe function for RAID Engine */
+static int fsl_re_probe(struct platform_device *ofdev)
+{
+ struct fsl_re_drv_private *re_priv;
+ struct device_node *np;
+ struct device_node *child;
+ u32 off;
+ u8 ridx = 0;
+ struct dma_device *dma_dev;
+ struct resource *res;
+ int rc;
+ struct device *dev = &ofdev->dev;
+
+ re_priv = devm_kzalloc(dev, sizeof(*re_priv), GFP_KERNEL);
+ if (!re_priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ /* IOMAP the entire RAID Engine region */
+ re_priv->re_regs = devm_ioremap(dev, res->start, resource_size(res));
+ if (!re_priv->re_regs)
+ return -EBUSY;
+
+ /* Program the RE mode */
+ out_be32(&re_priv->re_regs->global_config, FSL_RE_NON_DPAA_MODE);
+
+ /* Program Galois Field polynomial */
+ out_be32(&re_priv->re_regs->galois_field_config, FSL_RE_GFM_POLY);
+
+ dev_info(dev, "version %x, mode %x, gfp %x\n",
+ in_be32(&re_priv->re_regs->re_version_id),
+ in_be32(&re_priv->re_regs->global_config),
+ in_be32(&re_priv->re_regs->galois_field_config));
+
+ dma_dev = &re_priv->dma_dev;
+ dma_dev->dev = dev;
+ INIT_LIST_HEAD(&dma_dev->channels);
+ dma_set_mask(dev, DMA_BIT_MASK(40));
+
+ dma_dev->device_alloc_chan_resources = fsl_re_alloc_chan_resources;
+ dma_dev->device_tx_status = fsl_re_tx_status;
+ dma_dev->device_issue_pending = fsl_re_issue_pending;
+
+ dma_dev->max_xor = FSL_RE_MAX_XOR_SRCS;
+ dma_dev->device_prep_dma_xor = fsl_re_prep_dma_xor;
+ dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+
+ dma_dev->max_pq = FSL_RE_MAX_PQ_SRCS;
+ dma_dev->device_prep_dma_pq = fsl_re_prep_dma_pq;
+ dma_cap_set(DMA_PQ, dma_dev->cap_mask);
+
+ dma_dev->device_prep_dma_memcpy = fsl_re_prep_dma_memcpy;
+ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+
+ dma_dev->device_free_chan_resources = fsl_re_free_chan_resources;
+
+ re_priv->total_chans = 0;
+
+ re_priv->cf_desc_pool = dmam_pool_create("fsl_re_cf_desc_pool", dev,
+ FSL_RE_CF_CDB_SIZE,
+ FSL_RE_CF_CDB_ALIGN, 0);
+
+ if (!re_priv->cf_desc_pool) {
+ pr_err("No memory for fsl re_cf desc pool\n");
+ return -ENOMEM;
+ }
+
+ re_priv->hw_desc_pool = dmam_pool_create("fsl_re_hw_desc_pool", dev,
+ sizeof(struct fsl_re_hw_desc) * FSL_RE_RING_SIZE,
+ FSL_RE_FRAME_ALIGN, 0);
+ if (!re_priv->hw_desc_pool) {
+ pr_err("No memory for fsl re_hw desc pool\n");
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(dev, re_priv);
+
+ /* Parse Device tree to find out the total number of JQs present */
+ for_each_compatible_node(np, NULL, "fsl,raideng-v1.0-job-queue") {
+ rc = of_property_read_u32(np, "reg", &off);
+ if (rc) {
+ dev_err(dev, "Reg property not found in JQ node\n");
+ return -ENODEV;
+ }
+ /* Find out the Job Rings present under each JQ */
+ for_each_child_of_node(np, child) {
+ rc = of_device_is_compatible(child,
+ "fsl,raideng-v1.0-job-ring");
+ if (rc) {
+ fsl_re_chan_probe(ofdev, child, ridx++, off);
+ re_priv->total_chans++;
+ }
+ }
+ }
+
+ dma_async_device_register(dma_dev);
+
+ return 0;
+}
+
+static void fsl_re_remove_chan(struct fsl_re_chan *chan)
+{
+ dma_pool_free(chan->re_dev->hw_desc_pool, chan->inb_ring_virt_addr,
+ chan->inb_phys_addr);
+
+ dma_pool_free(chan->re_dev->hw_desc_pool, chan->oub_ring_virt_addr,
+ chan->oub_phys_addr);
+}
+
+static int fsl_re_remove(struct platform_device *ofdev)
+{
+ struct fsl_re_drv_private *re_priv;
+ struct device *dev;
+ int i;
+
+ dev = &ofdev->dev;
+ re_priv = dev_get_drvdata(dev);
+
+ /* Cleanup chan related memory areas */
+ for (i = 0; i < re_priv->total_chans; i++)
+ fsl_re_remove_chan(re_priv->re_jrs[i]);
+
+ /* Unregister the driver */
+ dma_async_device_unregister(&re_priv->dma_dev);
+
+ return 0;
+}
+
+static struct of_device_id fsl_re_ids[] = {
+ { .compatible = "fsl,raideng-v1.0", },
+ {}
+};
+
+static struct platform_driver fsl_re_driver = {
+ .driver = {
+ .name = "fsl-raideng",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_re_ids,
+ },
+ .probe = fsl_re_probe,
+ .remove = fsl_re_remove,
+};
+
+module_platform_driver(fsl_re_driver);
+
+MODULE_AUTHOR("Harninder Rai <harninder.rai@freescale.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Freescale RAID Engine Device Driver");
diff --git a/drivers/dma/fsl_raid.h b/drivers/dma/fsl_raid.h
new file mode 100644
index 0000000..69d743c
--- /dev/null
+++ b/drivers/dma/fsl_raid.h
@@ -0,0 +1,306 @@
+/*
+ * drivers/dma/fsl_raid.h
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ * Harninder Rai <harninder.rai@freescale.com>
+ * Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Rewrite:
+ * Xuelin Shi <xuelin.shi@freescale.com>
+
+ * Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define FSL_RE_MAX_CHANS 4
+#define FSL_RE_DPAA_MODE BIT(30)
+#define FSL_RE_NON_DPAA_MODE BIT(31)
+#define FSL_RE_GFM_POLY 0x1d000000
+#define FSL_RE_ADD_JOB(x) ((x) << 16)
+#define FSL_RE_RMVD_JOB(x) ((x) << 16)
+#define FSL_RE_CFG1_CBSI 0x08000000
+#define FSL_RE_CFG1_CBS0 0x00080000
+#define FSL_RE_SLOT_FULL_SHIFT 8
+#define FSL_RE_SLOT_FULL(x) ((x) >> FSL_RE_SLOT_FULL_SHIFT)
+#define FSL_RE_SLOT_AVAIL_SHIFT 8
+#define FSL_RE_SLOT_AVAIL(x) ((x) >> FSL_RE_SLOT_AVAIL_SHIFT)
+#define FSL_RE_PQ_OPCODE 0x1B
+#define FSL_RE_XOR_OPCODE 0x1A
+#define FSL_RE_MOVE_OPCODE 0x8
+#define FSL_RE_FRAME_ALIGN 16
+#define FSL_RE_BLOCK_SIZE 0x3 /* 4096 bytes */
+#define FSL_RE_CACHEABLE_IO 0x0
+#define FSL_RE_BUFFER_OUTPUT 0x0
+#define FSL_RE_INTR_ON_ERROR 0x1
+#define FSL_RE_DATA_DEP 0x1
+#define FSL_RE_ENABLE_DPI 0x0
+#define FSL_RE_RING_SIZE 0x400
+#define FSL_RE_RING_SIZE_MASK (FSL_RE_RING_SIZE - 1)
+#define FSL_RE_RING_SIZE_SHIFT 8
+#define FSL_RE_ADDR_BIT_SHIFT 4
+#define FSL_RE_ADDR_BIT_MASK (BIT(FSL_RE_ADDR_BIT_SHIFT) - 1)
+#define FSL_RE_ERROR 0x40000000
+#define FSL_RE_INTR 0x80000000
+#define FSL_RE_CLR_INTR 0x80000000
+#define FSL_RE_PAUSE 0x80000000
+#define FSL_RE_ENABLE 0x80000000
+#define FSL_RE_REG_LIODN_MASK 0x00000FFF
+
+#define FSL_RE_CDB_OPCODE_MASK 0xF8000000
+#define FSL_RE_CDB_OPCODE_SHIFT 27
+#define FSL_RE_CDB_EXCLEN_MASK 0x03000000
+#define FSL_RE_CDB_EXCLEN_SHIFT 24
+#define FSL_RE_CDB_EXCLQ1_MASK 0x00F00000
+#define FSL_RE_CDB_EXCLQ1_SHIFT 20
+#define FSL_RE_CDB_EXCLQ2_MASK 0x000F0000
+#define FSL_RE_CDB_EXCLQ2_SHIFT 16
+#define FSL_RE_CDB_BLKSIZE_MASK 0x0000C000
+#define FSL_RE_CDB_BLKSIZE_SHIFT 14
+#define FSL_RE_CDB_CACHE_MASK 0x00003000
+#define FSL_RE_CDB_CACHE_SHIFT 12
+#define FSL_RE_CDB_BUFFER_MASK 0x00000800
+#define FSL_RE_CDB_BUFFER_SHIFT 11
+#define FSL_RE_CDB_ERROR_MASK 0x00000400
+#define FSL_RE_CDB_ERROR_SHIFT 10
+#define FSL_RE_CDB_NRCS_MASK 0x0000003C
+#define FSL_RE_CDB_NRCS_SHIFT 6
+#define FSL_RE_CDB_DEPEND_MASK 0x00000008
+#define FSL_RE_CDB_DEPEND_SHIFT 3
+#define FSL_RE_CDB_DPI_MASK 0x00000004
+#define FSL_RE_CDB_DPI_SHIFT 2
+
+/*
+ * the largest cf block is 19*sizeof(struct cmpnd_frame), which is 304 bytes.
+ * here 19 = 1(cdb)+2(dest)+16(src), align to 64bytes, that is 320 bytes.
+ * the largest cdb block: struct pq_cdb which is 180 bytes, adding to cf block
+ * 320+180=500, align to 64bytes, that is 512 bytes.
+ */
+#define FSL_RE_CF_DESC_SIZE 320
+#define FSL_RE_CF_CDB_SIZE 512
+#define FSL_RE_CF_CDB_ALIGN 64
+
+struct fsl_re_ctrl {
+ /* General Configuration Registers */
+ __be32 global_config; /* Global Configuration Register */
+ u8 rsvd1[4];
+ __be32 galois_field_config; /* Galois Field Configuration Register */
+ u8 rsvd2[4];
+ __be32 jq_wrr_config; /* WRR Configuration register */
+ u8 rsvd3[4];
+ __be32 crc_config; /* CRC Configuration register */
+ u8 rsvd4[228];
+ __be32 system_reset; /* System Reset Register */
+ u8 rsvd5[252];
+ __be32 global_status; /* Global Status Register */
+ u8 rsvd6[832];
+ __be32 re_liodn_base; /* LIODN Base Register */
+ u8 rsvd7[1712];
+ __be32 re_version_id; /* Version ID register of RE */
+ __be32 re_version_id_2; /* Version ID 2 register of RE */
+ u8 rsvd8[512];
+ __be32 host_config; /* Host I/F Configuration Register */
+};
+
+struct fsl_re_chan_cfg {
+ /* Registers for JR interface */
+ __be32 jr_config_0; /* Job Queue Configuration 0 Register */
+ __be32 jr_config_1; /* Job Queue Configuration 1 Register */
+ __be32 jr_interrupt_status; /* Job Queue Interrupt Status Register */
+ u8 rsvd1[4];
+ __be32 jr_command; /* Job Queue Command Register */
+ u8 rsvd2[4];
+ __be32 jr_status; /* Job Queue Status Register */
+ u8 rsvd3[228];
+
+ /* Input Ring */
+ __be32 inbring_base_h; /* Inbound Ring Base Address Register - High */
+ __be32 inbring_base_l; /* Inbound Ring Base Address Register - Low */
+ __be32 inbring_size; /* Inbound Ring Size Register */
+ u8 rsvd4[4];
+ __be32 inbring_slot_avail; /* Inbound Ring Slot Available Register */
+ u8 rsvd5[4];
+ __be32 inbring_add_job; /* Inbound Ring Add Job Register */
+ u8 rsvd6[4];
+ __be32 inbring_cnsmr_indx; /* Inbound Ring Consumer Index Register */
+ u8 rsvd7[220];
+
+ /* Output Ring */
+ __be32 oubring_base_h; /* Outbound Ring Base Address Register - High */
+ __be32 oubring_base_l; /* Outbound Ring Base Address Register - Low */
+ __be32 oubring_size; /* Outbound Ring Size Register */
+ u8 rsvd8[4];
+ __be32 oubring_job_rmvd; /* Outbound Ring Job Removed Register */
+ u8 rsvd9[4];
+ __be32 oubring_slot_full; /* Outbound Ring Slot Full Register */
+ u8 rsvd10[4];
+ __be32 oubring_prdcr_indx; /* Outbound Ring Producer Index */
+};
+
+/*
+ * Command Descriptor Block (CDB) for unicast move command.
+ * In RAID Engine terms, memcpy is done through move command
+ */
+struct fsl_re_move_cdb {
+ __be32 cdb32;
+};
+
+/* Data protection/integrity related fields */
+#define FSL_RE_DPI_APPS_MASK 0xC0000000
+#define FSL_RE_DPI_APPS_SHIFT 30
+#define FSL_RE_DPI_REF_MASK 0x30000000
+#define FSL_RE_DPI_REF_SHIFT 28
+#define FSL_RE_DPI_GUARD_MASK 0x0C000000
+#define FSL_RE_DPI_GUARD_SHIFT 26
+#define FSL_RE_DPI_ATTR_MASK 0x03000000
+#define FSL_RE_DPI_ATTR_SHIFT 24
+#define FSL_RE_DPI_META_MASK 0x0000FFFF
+
+struct fsl_re_dpi {
+ __be32 dpi32;
+ __be32 ref;
+};
+
+/*
+ * CDB for GenQ command. In RAID Engine terminology, XOR is
+ * done through this command
+ */
+struct fsl_re_xor_cdb {
+ __be32 cdb32;
+ u8 gfm[16];
+ struct fsl_re_dpi dpi_dest_spec;
+ struct fsl_re_dpi dpi_src_spec[16];
+};
+
+/* CDB for no-op command */
+struct fsl_re_noop_cdb {
+ __be32 cdb32;
+};
+
+/*
+ * CDB for GenQQ command. In RAID Engine terminology, P/Q is
+ * done through this command
+ */
+struct fsl_re_pq_cdb {
+ __be32 cdb32;
+ u8 gfm_q1[16];
+ u8 gfm_q2[16];
+ struct fsl_re_dpi dpi_dest_spec[2];
+ struct fsl_re_dpi dpi_src_spec[16];
+};
+
+/* Compound frame */
+#define FSL_RE_CF_ADDR_HIGH_MASK 0x000000FF
+#define FSL_RE_CF_EXT_MASK 0x80000000
+#define FSL_RE_CF_EXT_SHIFT 31
+#define FSL_RE_CF_FINAL_MASK 0x40000000
+#define FSL_RE_CF_FINAL_SHIFT 30
+#define FSL_RE_CF_LENGTH_MASK 0x000FFFFF
+#define FSL_RE_CF_BPID_MASK 0x00FF0000
+#define FSL_RE_CF_BPID_SHIFT 16
+#define FSL_RE_CF_OFFSET_MASK 0x00001FFF
+
+struct fsl_re_cmpnd_frame {
+ __be32 addr_high;
+ __be32 addr_low;
+ __be32 efrl32;
+ __be32 rbro32;
+};
+
+/* Frame descriptor */
+#define FSL_RE_HWDESC_LIODN_MASK 0x3F000000
+#define FSL_RE_HWDESC_LIODN_SHIFT 24
+#define FSL_RE_HWDESC_BPID_MASK 0x00FF0000
+#define FSL_RE_HWDESC_BPID_SHIFT 16
+#define FSL_RE_HWDESC_ELIODN_MASK 0x0000F000
+#define FSL_RE_HWDESC_ELIODN_SHIFT 12
+#define FSL_RE_HWDESC_FMT_SHIFT 29
+#define FSL_RE_HWDESC_FMT_MASK (0x3 << FSL_RE_HWDESC_FMT_SHIFT)
+
+struct fsl_re_hw_desc {
+ __be32 lbea32;
+ __be32 addr_low;
+ __be32 fmt32;
+ __be32 status;
+};
+
+/* Raid Engine device private data */
+struct fsl_re_drv_private {
+ u8 total_chans;
+ struct dma_device dma_dev;
+ struct fsl_re_ctrl *re_regs;
+ struct fsl_re_chan *re_jrs[FSL_RE_MAX_CHANS];
+ struct dma_pool *cf_desc_pool;
+ struct dma_pool *hw_desc_pool;
+};
+
+/* Per job ring data structure */
+struct fsl_re_chan {
+ char name[16];
+ spinlock_t desc_lock; /* queue lock */
+ struct list_head ack_q; /* wait to acked queue */
+ struct list_head active_q; /* already issued on hw, not completed */
+ struct list_head submit_q;
+ struct list_head free_q; /* alloc available queue */
+ struct device *dev;
+ struct fsl_re_drv_private *re_dev;
+ struct dma_chan chan;
+ struct fsl_re_chan_cfg *jrregs;
+ int irq;
+ struct tasklet_struct irqtask;
+ u32 alloc_count;
+
+ /* hw descriptor ring for inbound queue*/
+ dma_addr_t inb_phys_addr;
+ struct fsl_re_hw_desc *inb_ring_virt_addr;
+ u32 inb_count;
+
+ /* hw descriptor ring for outbound queue */
+ dma_addr_t oub_phys_addr;
+ struct fsl_re_hw_desc *oub_ring_virt_addr;
+ u32 oub_count;
+};
+
+/* Async transaction descriptor */
+struct fsl_re_desc {
+ struct dma_async_tx_descriptor async_tx;
+ struct list_head node;
+ struct fsl_re_hw_desc hwdesc;
+ struct fsl_re_chan *re_chan;
+
+ /* hwdesc will point to cf_addr */
+ void *cf_addr;
+ dma_addr_t cf_paddr;
+
+ void *cdb_addr;
+ dma_addr_t cdb_paddr;
+ int status;
+};
--
1.9.1
^ permalink raw reply related
* Re: [v4,4/4] powernv: powerpc: Add winkle support for offline cpus
From: Shreyas B Prabhu @ 2014-12-15 7:03 UTC (permalink / raw)
To: Michael Ellerman; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <1418601701.19970.4.camel@ellerman.id.au>
On Monday 15 December 2014 05:31 AM, Michael Ellerman wrote:
> On Sun, 2014-12-14 at 17:22 +0530, Shreyas B Prabhu wrote:
>> On Sunday 14 December 2014 03:35 PM, Michael Ellerman wrote:
>>>> diff --git a/arch/powerpc/platforms/powernv/subcore.h b/arch/powerpc/platforms/powernv/subcore.h
>>>> index 148abc9..604eb40 100644
>>>> --- a/arch/powerpc/platforms/powernv/subcore.h
>>>> +++ b/arch/powerpc/platforms/powernv/subcore.h
>>>> @@ -15,4 +15,5 @@
>>>>
>>>> #ifndef __ASSEMBLY__
>>>> void split_core_secondary_loop(u8 *state);
>>>> +extern void update_subcore_sibling_mask(void);
>>>> #endif
>>>
>>> subcore.c isn't built for CONFIG_SMP=n, resulting in:
>>>
>>> setup.c:(.init.text+0x34b0): undefined reference to `.update_subcore_sibling_mask'
>>>
>>> I needed to add:
>>>
>>> +#else
>>> +static inline void update_subcore_sibling_mask(void) { };
>>> +#endif /* CONFIG_SMP */
>
>> Sorry I missed that.
>
> No worries.
>
> Can you please do a quick test with a SMP=n kernel.
>
> It looks like it should work, but it would be good to test.
>
I successfully tested SMP=n kernel with your next branch.
Thanks,
Shreyas
^ permalink raw reply
* [PATCHv2 1/8] kprobes: Fix kallsyms lookup across powerpc ABIv1 and ABIv2
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
Currently, all non-dot symbols are being treated as function descriptors
in ABIv1. This is incorrect and is resulting in perf probe not working:
# perf probe do_fork
Added new event:
Failed to write event: Invalid argument
Error: Failed to add events.
# dmesg | tail -1
[192268.073063] Could not insert probe at _text+768432: -22
perf probe bases all kernel probes on _text and writes,
for example, "p:probe/do_fork _text+768432" to
/sys/kernel/debug/tracing/kprobe_events. In-kernel, _text is being
considered to be a function descriptor and is resulting in the above
error.
Fix this by changing how we lookup symbol addresses on ppc64. We first
check for the dot variant of a symbol and look at the non-dot variant
only if that fails. In this manner, we avoid having to look at the
function descriptor.
While at it, also separate out how this works on ABIv2 where
we don't have dot symbols, but need to use the local entry point.
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
Mike,
I have restricted all changes to just the kprobe_lookup_name() macro. It has
now been split into different implementations for ABIv1 and ABIv2, hopefully
addressing the concerns you raised previously.
- Naveen
arch/powerpc/include/asm/kprobes.h | 63 ++++++++++++++++++++++++++------------
1 file changed, 44 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index af15d4d..039b583 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -41,34 +41,59 @@ typedef ppc_opcode_t kprobe_opcode_t;
#define MAX_INSN_SIZE 1
#ifdef CONFIG_PPC64
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+/* PPC64 ABIv2 needs local entry point */
+#define kprobe_lookup_name(name, addr) \
+{ \
+ addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); \
+ if (addr) \
+ addr = (kprobe_opcode_t *)ppc_function_entry(addr); \
+}
+#else
/*
- * 64bit powerpc uses function descriptors.
- * Handle cases where:
- * - User passes a <.symbol> or <module:.symbol>
- * - User passes a <symbol> or <module:symbol>
- * - User passes a non-existent symbol, kallsyms_lookup_name
- * returns 0. Don't deref the NULL pointer in that case
+ * 64bit powerpc ABIv1 uses function descriptors:
+ * - Check for the dot variant of the symbol first.
+ * - If that fails, try looking up the symbol provided.
+ *
+ * This ensures we always get to the actual symbol and not the descriptor.
+ * Also handle <module:symbol> format.
*/
#define kprobe_lookup_name(name, addr) \
{ \
- addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); \
- if (addr) { \
- char *colon; \
- if ((colon = strchr(name, ':')) != NULL) { \
- colon++; \
- if (*colon != '\0' && *colon != '.') \
- addr = (kprobe_opcode_t *)ppc_function_entry(addr); \
- } else if (name[0] != '.') \
- addr = (kprobe_opcode_t *)ppc_function_entry(addr); \
- } else { \
- char dot_name[KSYM_NAME_LEN]; \
+ char dot_name[MODULE_NAME_LEN + 1 + KSYM_NAME_LEN]; \
+ char *modsym; \
+ bool dot_appended = false; \
+ if ((modsym = strchr(name, ':')) != NULL) { \
+ modsym++; \
+ if (*modsym != '\0' && *modsym != '.') { \
+ /* Convert to <module:.symbol> */ \
+ strncpy(dot_name, name, modsym - name); \
+ dot_name[modsym - name] = '.'; \
+ dot_name[modsym - name + 1] = '\0'; \
+ strncat(dot_name, modsym, \
+ sizeof(dot_name) - (modsym - name) - 2);\
+ dot_appended = true; \
+ } else { \
+ dot_name[0] = '\0'; \
+ strncat(dot_name, name, sizeof(dot_name) - 1); \
+ } \
+ } else if (name[0] != '.') { \
dot_name[0] = '.'; \
dot_name[1] = '\0'; \
strncat(dot_name, name, KSYM_NAME_LEN - 2); \
- addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
+ dot_appended = true; \
+ } else { \
+ dot_name[0] = '\0'; \
+ strncat(dot_name, name, KSYM_NAME_LEN - 1); \
+ } \
+ addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
+ if (!addr && dot_appended) { \
+ /* Let's try the original non-dot symbol lookup */ \
+ addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); \
} \
}
-#endif
+#endif /* defined(_CALL_ELF) && _CALL_ELF == 2 */
+#endif /* CONFIG_PPC64 */
#define flush_insn_slot(p) do { } while (0)
#define kretprobe_blacklist_size 0
--
2.1.3
^ permalink raw reply related
* [PATCHv2 0/8] Fix perf probe issues on powerpc
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
This patchset fixes various issues with perf probe on powerpc across ABIv1 and
ABIv2:
- in the presence of DWARF debug-info,
- in the absence of DWARF, but with the symbol table, and
- in the absence of debug-info, but with kallsyms.
Applies cleanly on -tip. Tested on ppc64 BE and LE.
Changes from previous version:
Addressed various review comments from Mike Ellerman largely to generalize
changes. Some of the simpler patches have been retained in their previous form
to limit code churn, while others have been generalized by introducing arch
helpers. Individual patches have more details.
- Naveen
Naveen N. Rao (8):
kprobes: Fix kallsyms lookup across powerpc ABIv1 and ABIv2
perf probe: Improve detection of file/function name in the probe
pattern
perf probe powerpc: Fix symbol fixup issues due to ELF type
perf probe powerpc: Handle powerpc dot symbols
perf probe powerpc: Allow matching against dot symbols
perf tools powerpc: Fix PPC64 ELF ABIv2 symbol decoding
perf probe powerpc: Use DWARF info only if necessary
perf probe powerpc: Fixup function entry if using kallsyms lookup
arch/powerpc/include/asm/kprobes.h | 63 +++++++++++++++++++---------
tools/perf/arch/powerpc/Makefile | 1 +
tools/perf/arch/powerpc/util/sym-handling.c | 64 +++++++++++++++++++++++++++++
tools/perf/config/Makefile | 2 +
tools/perf/util/probe-event.c | 48 ++++++++++++++++++----
tools/perf/util/probe-event.h | 21 ++++++++++
tools/perf/util/symbol-elf.c | 5 ++-
tools/perf/util/symbol.c | 6 +++
tools/perf/util/symbol.h | 6 +++
9 files changed, 188 insertions(+), 28 deletions(-)
create mode 100644 tools/perf/arch/powerpc/util/sym-handling.c
--
2.1.3
^ permalink raw reply
* [PATCHv2 2/8] perf probe: Improve detection of file/function name in the probe pattern
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
Currently, perf probe considers patterns including a '.' to be a file.
However, this causes problems on powerpc ABIv1 where all functions have
a leading '.':
$ perf probe -F | grep schedule_timeout_interruptible
.schedule_timeout_interruptible
$ perf probe .schedule_timeout_interruptible
Semantic error :File always requires line number or lazy pattern.
Error: Command Parse Error.
Fix this by checking the probe pattern in more detail.
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
tools/perf/util/probe-event.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 28eb141..9943ff3 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -999,6 +999,24 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
arg = tmp;
}
+ /*
+ * Check arg is function or file name and copy it.
+ *
+ * We consider arg to be a file spec if and only if it satisfies
+ * all of the below criteria::
+ * - it does not include any of "+@%",
+ * - it includes one of ":;", and
+ * - it has a period '.' in the name.
+ *
+ * Otherwise, we consider arg to be a function specification.
+ */
+ c = 0;
+ if (!strpbrk(arg, "+@%") && (ptr = strpbrk(arg, ";:")) != NULL) {
+ /* This is a file spec if it includes a '.' before ; or : */
+ if (memchr(arg, '.', ptr-arg))
+ c = 1;
+ }
+
ptr = strpbrk(arg, ";:+@%");
if (ptr) {
nc = *ptr;
@@ -1009,10 +1027,9 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
if (tmp == NULL)
return -ENOMEM;
- /* Check arg is function or file and copy it */
- if (strchr(tmp, '.')) /* File */
+ if (c == 1)
pp->file = tmp;
- else /* Function */
+ else
pp->function = tmp;
/* Parse other options */
--
2.1.3
^ permalink raw reply related
* [PATCHv2 3/8] perf probe powerpc: Fix symbol fixup issues due to ELF type
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
If using the symbol table, symbol addresses are not being fixed up
properly, resulting in probes being placed at wrong addresses:
# perf probe do_fork
Added new event:
probe:do_fork (on do_fork)
You can now use it in all perf tools, such as:
perf record -e probe:do_fork -aR sleep 1
# cat /sys/kernel/debug/tracing/kprobe_events
p:probe/do_fork _text+635952
# printf "%x" 635952
9b430
# grep do_fork /boot/System.map
c0000000000ab430 T .do_fork
Fix by checking for ELF type ET_DYN used by ppc64 kernels.
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
tools/perf/util/symbol-elf.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 06fcd1b..7ac4e4c 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -683,7 +683,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
NULL) != NULL);
} else {
ss->adjust_symbols = ehdr.e_type == ET_EXEC ||
- ehdr.e_type == ET_REL;
+ ehdr.e_type == ET_REL ||
+ ehdr.e_type == ET_DYN;
}
ss->name = strdup(name);
--
2.1.3
^ permalink raw reply related
* [PATCHv2 4/8] perf probe powerpc: Handle powerpc dot symbols
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
Fix up various perf aspects related to ppc64's usage of dot functions:
- ignore leading '.' when generating event names and when looking for
existing events.
- use the proper prefix when ignoring SyS symbol lookups.
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
tools/perf/util/probe-event.c | 8 ++++++++
tools/perf/util/symbol.c | 6 ++++++
2 files changed, 14 insertions(+)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9943ff3..74b7fef 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2080,6 +2080,10 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
{
int i, ret;
+ /* Skip the leading dot on powerpc */
+ if (*base == '.')
+ base++;
+
/* Try no suffix */
ret = e_snprintf(buf, len, "%s", base);
if (ret < 0) {
@@ -2538,6 +2542,10 @@ int del_perf_probe_events(struct strlist *dellist)
event = str;
}
+ /* Skip the leading dot on powerpc */
+ if (event && *event == '.')
+ event++;
+
ret = e_snprintf(buf, 128, "%s:%s", group, event);
if (ret < 0) {
pr_err("Failed to copy event.");
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c24c5b8..e7b9bae 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -139,6 +139,12 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
if (na >= 10 && !strncmp(syma->name, "compat_SyS", 10))
return SYMBOL_B;
+ /* On powerpc, ignore the dot variants */
+ if (na >= 4 && !strncmp(syma->name, ".SyS", 4))
+ return SYMBOL_B;
+ if (na >= 11 && !strncmp(syma->name, ".compat_SyS", 11))
+ return SYMBOL_B;
+
return SYMBOL_A;
}
--
2.1.3
^ permalink raw reply related
* [PATCHv2 5/8] perf probe powerpc: Allow matching against dot symbols
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
Allow perf probe to work on powerpc ABIv1 without the need to specify
the leading dot '.' for functions. 'perf probe do_fork' works with this
patch.
Introduce HAVE_ARCH_SYMBOL_HANDLING to indicate need for special
handling of symbols. In this patch, we override probe_function_filter()
on powerpc to account for dot symbols.
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
Changes from the previous patchset:
Introduced arch helper to override the way probe function filter works.
tools/perf/arch/powerpc/Makefile | 1 +
tools/perf/arch/powerpc/util/sym-handling.c | 28 ++++++++++++++++++++++++++++
tools/perf/config/Makefile | 1 +
tools/perf/util/probe-event.c | 10 +++++-----
tools/perf/util/probe-event.h | 5 +++++
5 files changed, 40 insertions(+), 5 deletions(-)
create mode 100644 tools/perf/arch/powerpc/util/sym-handling.c
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 6f7782b..1c3d435 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -3,4 +3,5 @@ PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
endif
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/sym-handling.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
new file mode 100644
index 0000000..0a77825
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -0,0 +1,28 @@
+/*
+ * Special symbol handling for PowerPC:
+ * - Handle dot symbols on ABIv1
+ *
+ * Copyright (C) 2014 Naveen N Rao, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "map.h"
+#include "symbol.h"
+#include "probe-event.h"
+
+int probe_function_filter(struct map *map __maybe_unused, struct symbol *sym)
+{
+ if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) {
+ if ((strcmp(looking_function_name, sym->name) == 0) ||
+ (sym->name[0] == '.' && looking_function_name[0] != '.' &&
+ strcmp(looking_function_name, sym->name+1) == 0)) {
+ num_matched_functions++;
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5d4b039..35cf934 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -383,6 +383,7 @@ ifeq ($(ARCH),powerpc)
ifndef NO_DWARF
CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
endif
+ CFLAGS += -DHAVE_ARCH_SYMBOL_HANDLING
endif
ifndef NO_LIBUNWIND
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 74b7fef..7eb9b27 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -50,6 +50,8 @@
#define PERFPROBE_GROUP "probe"
bool probe_event_dry_run; /* Dry run flag */
+char *looking_function_name;
+int num_matched_functions;
#define semantic_error(msg ...) pr_err("Semantic error :" msg)
@@ -2210,11 +2212,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
return ret;
}
-static char *looking_function_name;
-static int num_matched_functions;
-
-static int probe_function_filter(struct map *map __maybe_unused,
- struct symbol *sym)
+#ifndef HAVE_ARCH_SYMBOL_HANDLING
+int probe_function_filter(struct map *map __maybe_unused, struct symbol *sym)
{
if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
strcmp(looking_function_name, sym->name) == 0) {
@@ -2223,6 +2222,7 @@ static int probe_function_filter(struct map *map __maybe_unused,
}
return 1;
}
+#endif /* HAVE_ARCH_SYMBOL_HANDLING */
#define strdup_or_goto(str, label) \
({ char *__p = strdup(str); if (!__p) goto label; __p; })
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e01e994..8564451 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -7,6 +7,8 @@
#include "strfilter.h"
extern bool probe_event_dry_run;
+extern char *looking_function_name;
+extern int num_matched_functions;
/* kprobe-tracer and uprobe-tracer tracing point */
struct probe_trace_point {
@@ -136,6 +138,9 @@ extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
extern int show_available_funcs(const char *module, struct strfilter *filter,
bool user);
+extern int probe_function_filter(struct map *map __maybe_unused,
+ struct symbol *sym);
+
/* Maximum index number of event-name postfix */
#define MAX_EVENT_INDEX 1024
--
2.1.3
^ permalink raw reply related
* [PATCHv2 6/8] perf tools powerpc: Fix PPC64 ELF ABIv2 symbol decoding
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
PPC64 ELF ABIv2 has a Global Entry Point (GEP) and a Local Entry Point
(LEP). For purposes of probing, we need the LEP. Offset to the LEP is
encoded in st_other.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
Changes from previous patchset:
Simplified logic by adding dependancy on HAVE_ARCH_SYMBOL_HANDLING. Also
generalized arch_elf_sym_decode() to be suitable for other architectures in
future.
tools/perf/arch/powerpc/util/sym-handling.c | 10 ++++++++++
tools/perf/util/symbol-elf.c | 2 ++
tools/perf/util/symbol.h | 6 ++++++
3 files changed, 18 insertions(+)
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index 0a77825..a27bfaf 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -1,8 +1,10 @@
/*
* Special symbol handling for PowerPC:
* - Handle dot symbols on ABIv1
+ * - Decode offset from Global entry point to Local entry point on ABIv2
*
* Copyright (C) 2014 Naveen N Rao, IBM Corporation.
+ * Copyright (C) 2014 Ananth N Mavinakayanahalli, IBM Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,3 +28,11 @@ int probe_function_filter(struct map *map __maybe_unused, struct symbol *sym)
}
return 1;
}
+
+inline void arch_elf_sym_decode(GElf_Sym *sym __maybe_unused)
+{
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+ if (sym && sym->st_other)
+ sym->st_value += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
+#endif
+}
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 7ac4e4c..557b63b 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -902,6 +902,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
(sym.st_value & 1))
--sym.st_value;
+ arch_elf_sym_decode(&sym);
+
if (dso->kernel || kmodule) {
char dso_name[PATH_MAX];
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 9d602e9..9e03cdf 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -294,4 +294,10 @@ int compare_proc_modules(const char *from, const char *to);
int setup_list(struct strlist **list, const char *list_str,
const char *list_name);
+#ifdef HAVE_ARCH_SYMBOL_HANDLING
+extern void arch_elf_sym_decode(GElf_Sym *sym __maybe_unused);
+#else
+static inline void arch_elf_sym_decode(GElf_Sym *sym __maybe_unused) { }
+#endif
+
#endif /* __PERF_SYMBOL */
--
2.1.3
^ permalink raw reply related
* [PATCHv2 7/8] perf probe powerpc: Use DWARF info only if necessary
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
Use symbol table lookups by default if DWARF is not necessary, since
powerpc ABIv2 encodes local entry points in the symbol table and the
function entry address in DWARF may not be appropriate for kprobes, as
described here:
https://sourceware.org/bugzilla/show_bug.cgi?id=17638
"The DWARF address ranges deliberately include the *whole* function,
both global and local entry points."
...
"If you want to set probes on a local entry point, you should look up
the symbol in the main symbol table (not DWARF), and check the st_other
bits; they will indicate whether the function has a local entry point,
and what its offset from the global entry point is. Note that GDB does
the same when setting a breakpoint on a function entry."
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
Changes from previous patchset:
Generalize and introduce helper to prefer symbol table over DWARF.
tools/perf/arch/powerpc/util/sym-handling.c | 9 +++++++++
tools/perf/config/Makefile | 1 +
tools/perf/util/probe-event.c | 6 ++++++
tools/perf/util/probe-event.h | 6 ++++++
4 files changed, 22 insertions(+)
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index a27bfaf..22fc2e6 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -36,3 +36,12 @@ inline void arch_elf_sym_decode(GElf_Sym *sym __maybe_unused)
sym->st_value += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
#endif
}
+
+inline bool prefer_symtab(void)
+{
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 35cf934..849f686 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -384,6 +384,7 @@ ifeq ($(ARCH),powerpc)
CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
endif
CFLAGS += -DHAVE_ARCH_SYMBOL_HANDLING
+ CFLAGS += -DARCH_PREFER_SYMTAB
endif
ifndef NO_LIBUNWIND
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 7eb9b27..dfc3151 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2373,6 +2373,12 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
}
}
+ if (prefer_symtab() && !perf_probe_event_need_dwarf(pev)) {
+ ret = find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
+ if (ret > 0)
+ return ret; /* Found in symbol table */
+ }
+
/* Convert perf_probe_event with debuginfo */
ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
if (ret != 0)
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 8564451..5f92906 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -141,6 +141,12 @@ extern int show_available_funcs(const char *module, struct strfilter *filter,
extern int probe_function_filter(struct map *map __maybe_unused,
struct symbol *sym);
+#ifdef ARCH_PREFER_SYMTAB
+extern bool prefer_symtab(void);
+#else
+static inline bool prefer_symtab(void) { return false; };
+#endif
+
/* Maximum index number of event-name postfix */
#define MAX_EVENT_INDEX 1024
--
2.1.3
^ permalink raw reply related
* [PATCHv2 8/8] perf probe powerpc: Fixup function entry if using kallsyms lookup
From: Naveen N. Rao @ 2014-12-15 14:50 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, acme, mpe
In-Reply-To: <cover.1418654435.git.naveen.n.rao@linux.vnet.ibm.com>
On powerpc ABIv2, if no debug-info is found and we use kallsyms, we need
to fixup the function entry to point to the local entry point. Use
offset of 8 since current toolchains always generate 2 instructions (8
bytes).
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
Changes:
Generalize and introduce helper to post-process trace point.
tools/perf/arch/powerpc/util/sym-handling.c | 17 +++++++++++++++++
tools/perf/util/probe-event.c | 1 +
tools/perf/util/probe-event.h | 10 ++++++++++
3 files changed, 28 insertions(+)
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index 22fc2e6..30c8797 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -45,3 +45,20 @@ inline bool prefer_symtab(void)
return false;
#endif
}
+
+void arch_fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
+ struct probe_trace_event *tev __maybe_unused,
+ struct map *map __maybe_unused)
+{
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+ /*
+ * If we used kallsyms, we should fixup the function entry address here.
+ * ppc64 ABIv2 local entry point is currently always 2 instructions (8 bytes)
+ * after the global entry point. Fix this if it ever changes.
+ */
+ if (!pev->uprobes && map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
+ tev->point.address += 8;
+ tev->point.offset += 8;
+ }
+#endif
+}
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index dfc3151..85f37a4 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2340,6 +2340,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
strdup_or_goto(pev->args[i].type,
nomem_out);
}
+ arch_fix_tev_from_maps(pev, tev, map);
}
out:
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5f92906..335a6a4 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -147,6 +147,16 @@ extern bool prefer_symtab(void);
static inline bool prefer_symtab(void) { return false; };
#endif
+#ifdef HAVE_ARCH_SYMBOL_HANDLING
+extern void arch_fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
+ struct probe_trace_event *tev __maybe_unused,
+ struct map *map __maybe_unused);
+#else
+static inline void arch_fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
+ struct probe_trace_event *tev __maybe_unused,
+ struct map *map __maybe_unused) { }
+#endif
+
/* Maximum index number of event-name postfix */
#define MAX_EVENT_INDEX 1024
--
2.1.3
^ permalink raw reply related
* [PATCH 0/2] Add SDHCI support for APM X-Gene SoC using ARASAN SDHCI controller.
From: Suman Tripathi @ 2014-12-15 17:01 UTC (permalink / raw)
To: chris, anton, arnd
Cc: devicetree, Suman Tripathi, jcm, linux-mmc, patches, ddutile,
linuxppc-dev, linux-arm-kernel
Due to the fact that the existing of-arasan driver works with 32-bit platforms.
This patch tweaks existing of-arasan driver to work with 64-bit X-Gene
platform using IOMMU translation.
Signed-off-by: Suman Tripathi <stripathi@apm.com>
---
Suman Tripathi (2):
mmc: host: arasan: Add addition of-arasan quirks and add IOMMU
support.
arm64: dts: Add APM X-Gene SDHCI DTS node.
arch/arm64/boot/dts/apm-storm.dtsi | 43 ++++++++++++++++++++++++++++++
drivers/mmc/host/Kconfig | 1 +
drivers/mmc/host/sdhci-of-arasan.c | 54 ++++++++++++++++++++++++++++++++++++++
drivers/mmc/host/sdhci-pltfm.c | 12 +++++++++
4 files changed, 110 insertions(+)
--
1.8.2.1
^ permalink raw reply
* [PATCH 2/2] arm64: dts: Add APM X-Gene SDHCI DTS node.
From: Suman Tripathi @ 2014-12-15 17:01 UTC (permalink / raw)
To: chris, anton, arnd
Cc: devicetree, Suman Tripathi, jcm, linux-mmc, patches, ddutile,
linuxppc-dev, linux-arm-kernel
In-Reply-To: <1418662867-9210-1-git-send-email-stripathi@apm.com>
This patch adds the ahbclk and sdhciclk clock nodes and
the sdhci device tree nodes of APM X-Gene SDHCI controller.
Signed-off-by: Suman Tripathi <stripathi@apm.com>
---
arch/arm64/boot/dts/apm-storm.dtsi | 43 ++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
index c0aceef..18e291b 100644
--- a/arch/arm64/boot/dts/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
@@ -144,6 +144,40 @@
clock-output-names = "socplldiv2";
};
+ ahbclk: ahbclk@1f2ac000 {
+ compatible = "apm,xgene-device-clock";
+ #clock-cells = <1>;
+ clocks = <&socplldiv2 0>;
+ reg = <0x0 0x1f2ac000 0x0 0x1000
+ 0x0 0x17000000 0x0 0x2000>;
+ reg-names = "csr-reg", "div-reg";
+ csr-offset = <0x0>;
+ csr-mask = <0x1>;
+ enable-offset = <0x8>;
+ enable-mask = <0x1>;
+ divider-offset = <0x164>;
+ divider-width = <0x5>;
+ divider-shift = <0x0>;
+ clock-output-names = "ahbclk";
+ };
+
+ sdioclk: sdioclk@1f2ac000 {
+ compatible = "apm,xgene-device-clock";
+ #clock-cells = <1>;
+ clocks = <&socplldiv2 0>;
+ reg = <0x0 0x1f2ac000 0x0 0x1000
+ 0x0 0x17000000 0x0 0x2000>;
+ reg-names = "csr-reg", "div-reg";
+ csr-offset = <0x0>;
+ csr-mask = <0x2>;
+ enable-offset = <0x8>;
+ enable-mask = <0x2>;
+ divider-offset = <0x178>;
+ divider-width = <0x8>;
+ divider-shift = <0x0>;
+ clock-output-names = "sdioclk";
+ };
+
qmlclk: qmlclk {
compatible = "apm,xgene-device-clock";
#clock-cells = <1>;
@@ -397,6 +431,15 @@
clocks = <&rtcclk 0>;
};
+ sdhc0: sdhc@1c000000 {
+ device_type = "sdhc";
+ compatible = "arasan,sdhci-8.9a";
+ reg = <0x0 0x1c000000 0x0 0x100>;
+ interrupts = <0x0 0x49 0x4>;
+ clock-names = "clk_xin", "clk_ahb";
+ clocks = <&sdioclk 0>, <&ahbclk 0>;
+ };
+
menet: ethernet@17020000 {
compatible = "apm,xgene-enet";
status = "disabled";
--
1.8.2.1
^ permalink raw reply related
* [PATCH 1/2] mmc: host: arasan: Add addition of-arasan quirks and add IOMMU support.
From: Suman Tripathi @ 2014-12-15 17:01 UTC (permalink / raw)
To: chris, anton, arnd
Cc: devicetree, Suman Tripathi, jcm, linux-mmc, patches, ddutile,
linuxppc-dev, linux-arm-kernel
In-Reply-To: <1418662867-9210-1-git-send-email-stripathi@apm.com>
Due to the fact that the existing of-arasan driver works with 32-bit platforms.
This patch tweaks existing of-arasan driver to work with 64-bit platform using
IOMMU translation.
In addition it adds support for more quirks and quirks2 obtained from device tree
inside the generic sdhci-platform(sdhci-pltfm.c) driver.
Signed-off-by: Suman Tripathi <stripathi@apm.com>
---
drivers/mmc/host/Kconfig | 1 +
drivers/mmc/host/sdhci-of-arasan.c | 54 ++++++++++++++++++++++++++++++++++++++
drivers/mmc/host/sdhci-pltfm.c | 12 +++++++++
3 files changed, 67 insertions(+)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 4511358..0c6dc47 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -108,6 +108,7 @@ config MMC_SDHCI_OF_ARASAN
tristate "SDHCI OF support for the Arasan SDHCI controllers"
depends on MMC_SDHCI_PLTFM
depends on OF
+ select MMC_SDHCI_IO_ACCESSORS
help
This selects the Arasan Secure Digital Host Controller Interface
(SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index 5bd1092..c0e0c9b 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -20,6 +20,10 @@
*/
#include <linux/module.h>
+#if defined(CONFIG_IOMMU_SUPPORT)
+#include <linux/amba/bus.h>
+#include <linux/iommu.h>
+#endif
#include "sdhci-pltfm.h"
#define SDHCI_ARASAN_CLK_CTRL_OFFSET 0x2c
@@ -34,8 +38,46 @@
*/
struct sdhci_arasan_data {
struct clk *clk_ahb;
+#if defined(CONFIG_IOMMU_SUPPORT)
+ struct iommu_domain *domain;
+#endif
};
+static void sdhci_arasan_write_l(struct sdhci_host *host, u32 val, int reg)
+{
+#if defined(CONFIG_IOMMU_SUPPORT)
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
+ /*
+ * This allows the arasan IP to integrate with 64-bit platform.
+ * As the AHB dma masters generates 32-bit address so it needs
+ * IO translation of 32-bit to 42-bit AXI address with help of IOMMU.
+ */
+ if (reg == SDHCI_DMA_ADDRESS) {
+ phys_addr_t dma_addr = sg_dma_address(host->data->sg);
+ sdhci_arasan->domain->ops->map(sdhci_arasan->domain, 0,
+ dma_addr, 0, 0);
+ }
+#endif
+ writel(val, host->ioaddr + reg);
+}
+
+static u32 xgene_sdhci_readl(struct sdhci_host *host, int reg)
+{
+#if defined(CONFIG_IOMMU_SUPPORT)
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
+
+ if (reg == SDHCI_INT_STATUS ) {
+ if ((readl(host->ioaddr + reg) & SDHCI_INT_DATA_MASK) ==
+ SDHCI_INT_DMA_END)
+ sdhci_arasan->domain->ops->unmap(sdhci_arasan->domain,
+ 0, 0);
+ }
+#endif
+ return readl(host->ioaddr + reg);
+}
+
static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)
{
u32 div;
@@ -58,6 +100,8 @@ static struct sdhci_ops sdhci_arasan_ops = {
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
+ .write_l = sdhci_arasan_write_l,
+ .read_l = xgene_sdhci_readl,
};
static struct sdhci_pltfm_data sdhci_arasan_pdata = {
@@ -162,6 +206,16 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
goto clk_dis_ahb;
}
+#if defined(CONFIG_IOMMU_SUPPORT)
+ sdhci_arasan->domain = iommu_domain_alloc(&amba_bustype);
+ if (!sdhci_arasan->domain) {
+ dev_err(&pdev->dev, "Unable to allocate iommu domain\n");
+ return PTR_ERR(sdhci_arasan->domain);
+ }
+
+ iommu_attach_device(sdhci_arasan->domain, &pdev->dev);
+#endif
+
host = sdhci_pltfm_init(pdev, &sdhci_arasan_pdata, 0);
if (IS_ERR(host)) {
ret = PTR_ERR(host);
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 7e834fb..08a97dc 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -90,6 +90,18 @@ void sdhci_get_of_property(struct platform_device *pdev)
if (of_get_property(np, "broken-cd", NULL))
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ if (of_get_property(np, "delay-after-power", NULL))
+ host->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER;
+
+ if (of_get_property(np, "no-hispd", NULL))
+ host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+
+ if (of_get_property(np, "broken-adma", NULL))
+ host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
+
+ if (of_get_property(np, "no-cmd23", NULL))
+ host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+
if (of_get_property(np, "no-1-8-v", NULL))
host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
--
1.8.2.1
^ permalink raw reply related
* PROBLEM: USB isochronous urb leak on EHCI driver
From: Michael Tessier @ 2014-12-15 20:53 UTC (permalink / raw)
To: leoli@freescale.com
Cc: linux-usb@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
[-- Attachment #1: Type: text/plain, Size: 4156 bytes --]
Hi,
I am dealing with a USB EHCI driver bug. Here is the info:
My configuration:
-----------------
Host: Freescale i.MX512 with ARM Cortex A8 (USB 2.0 host controller)
Linux kernel: 2.6.31, using EHCI USB driver
Hub: 4-PORT USB 1.1 HUB (Texas Instruments PN: tusb2046b)
Devices: 4 USB 1.1 audio codecs (Texas Instruments PN: pcm2901)
Note: each codec is being used in R/W access, so with 4 codecs, I have
4 playback and 4 capture streams.
My problem:
-----------
I have usb urb leaks when connecting more than 1 codec to the USB 1.1
Hub. (the result is that some of the audio data is not transferred,
part of the sound is simply missing) No problem when using only 1
of the 4 codecs connected to the hub; When I connect a second codec,
the sound quality starts to degrade. With 3 codecs, we just cannot
recognize a speach.
Tests and observations:
-----------------------
Since I have 3 usb ports available on the i.MX512, I tried to connect
3 codecs directly on USB ports: the sound is perfect on each of the
three ports.
I bought a consumer USB 2.0 Hub: no problem when using 3 codecs
connected to that Hub, however, the audio will completly stop on all
channels when connecting the 4th codec.
I checked the communication between the Hub (USB 1.1) and the Host
controller (USB 2.0) with a scope and concluded that the
communication speed is 1.5 MBytes/s has expected (so the
communication is downgraded to USB 1.1, since codecs and hub are USB
1.1 devices).
Also, I know that there is physically enough bandwidth to
transfer the data for two reasons:
1) I have an older CPU with a USB 1.1 host controller (using the OHCI
driver), using the same hub and the same codecs: works like a champ,
using less than 50% of the available bandwidth (observed with a
scope)
2) 1 audio stream is 32khz-mono, 16 bits = 64 kB/s,
4 codecs = 8 streams(R/W) x 64 kB/s = 512 kB/s (out of 1.5MB/s)
I noticed that my sound problem starts happening with only 2 codecs
(4 streams, 256 kB/s). I first thought that it was a bandwidth
limitation, so I decided to connect only 1 codec using more bandwidth.
I configured it to 48khz-stereo (16-bits), using 384 kB/s for both
read and write streams: no problem. With that configuration, the
scope shows about 30% of total bandwidth usage (300us used out of 1ms
periods). Then, I added a second codec (48khz-stereo-16bits): very
strange, now the total bandwidth usage felt down to about 200us, which
seems to keep the same, whatever the number of codec I add (I also
tried 3 and 4...). So it looks like the scheduler is not able to
properly allocate Isochronous time slots when more than one device is
connected to the hub. However, without the hub, it works perfectly.
Another interresting fact is that at application level, the Read and
Write operations are returning the good amount of bytes read/written.
This is not the case at kernel level: I noticed that function
"usb_submit_urb" (from /drivers/usb/core/urb.c) will only tranfer
part of the "urbs" when the sound is degraded. I tried to figure out
where the leak comes from without success. Also, there are no error
messages from kernel so everything appears to work well, excepted
that part of the sound is missing!
I can't change my hardware (this is in the hand of customers), so
the only possible solution for me is to correct the software.
I tried to change my ehci driver with the one from kernel 2.6.39.4
but did not work, same problem.
Question:
---------
Before attempting to upgrade to an earlier kernel driver (this is
a fairly big amount of work), I would really like to know if this
problem would still be in the 3.x kernels. Has anyone seen that
issue in 3.x kernels?
I am pretty new to USB driver debugging, so any ideas of where/how
to find solutions will be appreciated. Thank you very much in advance
for the support. Also don't hesitate to redirect me if I'm not at the
right place to ask these questions. I can also provide some code if
someone need it to help.
Attached is a dump of my "dmesg" after startup.
Michael Tessier
[-- Attachment #2: dmesg.txt --]
[-- Type: text/plain, Size: 9134 bytes --]
<5>Linux version 2.6.31-770-g0e46b52-0897 (michael.tessier@vsvr-compile-01.pocatec.com) (gcc version 4.1.2) #12 PREEMPT Mon Nov 24 18:34:19 EST 2014
<4>CPU: ARMv7 Processor [412fc085] revision 5 (ARMv7), cr=10c53c7f
<4>CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
<4>Machine: MX51 Xanthus Board
<4>Memory policy: ECC disabled, Data cache writeback
<7>On node 0 totalpages: 65536
<7>free_area_init_node: node 0, pgdat c02f137c, node_mem_map c0307000
<7> DMA zone: 128 pages used for memmap
<7> DMA zone: 0 pages reserved
<7> DMA zone: 16256 pages, LIFO batch:3
<7> Normal zone: 384 pages used for memmap
<7> Normal zone: 48768 pages, LIFO batch:15
<4>Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
<5>Kernel command line: console=ttymxc2,115200 CNFGmagic=XATS CNFGversion=1.0.0.0 vendorID=EXPT platformID=LINX productID=XATS mac1=00:1D:9E:00:17:2e mac2=00:1D:9E:00:17:2f XanthusPart=8100050 XanthusSerial=51 XanthusRevLevel=-- UnitPart=0 UnitSerial=0 UnitRevLevel=0 ip= UBversion=1.5.0.0 ethcpu=eth0 root=/dev/ram rw ramdisk_size=55000
<4>PID hash table entries: 1024 (order: 10, 4096 bytes)
<6>Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
<6>Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
<6>Memory: 256MB = 256MB total
<5>Memory: 254000KB available (2660K code, 208K data, 104K init, 0K highmem)
<6>SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
<6>NR_IRQS:368
<6>MXC IRQ initialized
<6>MXC_Early serial console at MMIO 0x7000c000 (options '115200')
<6>console [ttymxc2] enabled
<4>Console: colour dummy device 80x30
<6>Calibrating delay loop... 575.07 BogoMIPS (lpj=2875392)
<4>Mount-cache hash table entries: 512
<6>CPU: Testing write buffer coherency: ok
<6>NET: Registered protocol family 16
<6>i.MX IRAM pool: 128 KB@0xd0840000
<6>IRAM READY
<6>CPU is i.MX51 Revision 3.0
<6>MXC GPIO hardware
<4>XANTHUS FPGA irq controler :197
<4>ks8851: mac(00:1d:9e:00:17:2f)
<4>XANTHUS FPGA VERSION: 0.1.0.0
<6>Using SDMA I.API
<6>MXC DMA API initialized
<4>bio: create slab <bio-0> at 0
<5>SCSI subsystem initialized
<7>libata version 3.00 loaded.
<6>CSPI: mxc_spi-0 probed
<6>mxc_spi mxc_spi.0: registering loopback device 'spidev'
<6>mxc_spi mxc_spi.0: registering loopback device 'spidev'
<6>mxc_spi mxc_spi.0: registering loopback device 'spidev'
<6>MXC I2C driver
<6>MXC HS I2C driver
<6>NET: Registered protocol family 2
<6>IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
<7>Switched to high resolution mode on CPU 0
<6>TCP established hash table entries: 8192 (order: 4, 65536 bytes)
<6>TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
<6>TCP: Hash tables configured (established 8192 bind 8192)
<6>TCP reno registered
<6>NET: Registered protocol family 1
<6>Trying to unpack rootfs image as initramfs...
<6>rootfs image is not initramfs (no cpio magic); looks like an initrd
<6>Freeing initrd memory: 2604K
<6>LPMode driver module loaded
<6>msgmni has been set to 501
<6>io scheduler noop registered (default)
<4>Class created!
<6>Triggered GPIO driver. Boundary Devices
<6>XANTHUS Serial: 8250/16550 driver, 1 ports, IRQ sharing disabled
<6>serial8250.0: ttyS0 at MMIO 0xb0100000 (irq = 352) is a 16550A
<6>Serial: MXC Internal UART driver
<6>mxcintuart.0: ttymxc0 at MMIO 0x73fbc000 (irq = 31) is a Freescale i.MX
<6>mxcintuart.1: ttymxc1 at MMIO 0x73fc0000 (irq = 32) is a Freescale i.MX
<6>mxcintuart.2: ttymxc2 at MMIO 0x7000c000 (irq = 33) is a Freescale i.MX
<6>console handover: boot [ttymxc2] -> real [ttymxc2]
<6>brd: module loaded
<6>loop: module loaded
<3>pata_fsl pata_fsl: rchan=29 wchan=28
<6>scsi0 : pata_fsl
<6>ata1: PATA max UDMA/100 irq 70
<6>FEC Ethernet Driver
<3>FEC: fec_probe name:fec, id:0, net name:eth0, index:0
<3>FEC: mac(00:1d:9e:00:17:2e)
<6>ata1.00: CFA: TRANSCEND, 20100202, max UDMA/66
<6>ata1.00: 994896 sectors, multi 0: LBA
<6>ata1.00: configured for UDMA/66
<5>scsi 0:0:0:0: Direct-Access ATA TRANSCEND 2010 PQ: 0 ANSI: 5
<5>sd 0:0:0:0: [sda] 994896 512-byte logical blocks: (509 MB/485 MiB)
<5>sd 0:0:0:0: [sda] Write Protect is off
<7>sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
<5>sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
<6> sda: sda1 sda2 sda3 sda4
<5>sd 0:0:0:0: [sda] Attached SCSI disk
<6>fec_enet_mii_bus: probed
<4>IEEE1588: ptp-timer is unavailable
<6>rtc-ds1307 3-0068: rtc core: registered ds1340 as rtc0
<6>i2c /dev entries driver
<6>Xanthus WatchDog Driver 1.2
<4>clk: Unable to get requested clock: wdog_clk
<6>XANTHUS Boot - WDOG Rst - Soft Reset (10010,1)
<6>Xanthus Watchdog # 0 Timer: initial timeout 60 sec
<6>TCP cubic registered
<6>NET: Registered protocol family 17
<6>VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 2
<6>rtc-ds1307 3-0068: setting system clock to 2000-01-01 00:00:44 UTC (946684844)
<5>RAMDISK: gzip image found at block 0
<4>VFS: Mounted root (ext2 filesystem) on device 1:0.
<6>Freeing init memory: 104K
<6>XANTHUS ks8851_mll: Driver version 1.00.
<6>XANTHUS: ks8851_probe name:ks8851_mll, id:0, net name:eth1, index:0
<6>ks8851 hard reset
<6>ks8851_mll ks8851_mll.0: message enable is 31
<6>KS_CIDER:8872
<6>ks8851_mll ks8851_mll.0: the selftest passes
<6>XANTHUS: ks_soft_reset
<6>XANTHUS: KS8851 mac(00:1d:9e:00:17:2f)
<6>ks8851_mll Found chip, family: 0x88, id: 0x7, rev: 0x1
<6>Ethernet Channel Bonding Driver: v3.5.0 (November 4, 2008)
<6>bonding: MII link monitoring set to 100 ms
<6>usbcore: registered new interface driver usbfs
<6>usbcore: registered new interface driver hub
<6>usbcore: registered new device driver usb
<6>ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
<6>fsl-ehci fsl-ehci.0: Freescale On-Chip EHCI Host Controller
<6>fsl-ehci fsl-ehci.0: new USB bus registered, assigned bus number 1
<6>fsl-ehci fsl-ehci.0: irq 18, io base 0x73f80000
<6>fsl-ehci fsl-ehci.0: USB 2.0 started, EHCI 1.00
<6>usb usb1: configuration #1 chosen from 1 choice
<6>hub 1-0:1.0: USB hub found
<6>hub 1-0:1.0: 1 port detected
<6>fsl-ehci fsl-ehci.1: Freescale On-Chip EHCI Host Controller
<6>fsl-ehci fsl-ehci.1: new USB bus registered, assigned bus number 2
<6>fsl-ehci fsl-ehci.1: irq 14, io base 0x73f80200
<6>fsl-ehci fsl-ehci.1: USB 2.0 started, EHCI 1.00
<6>usb usb2: configuration #1 chosen from 1 choice
<6>hub 2-0:1.0: USB hub found
<6>hub 2-0:1.0: 1 port detected
<6>fsl-ehci fsl-ehci.2: Freescale On-Chip EHCI Host Controller
<6>fsl-ehci fsl-ehci.2: new USB bus registered, assigned bus number 3
<6>fsl-ehci fsl-ehci.2: irq 16, io base 0x73f80400
<6>fsl-ehci fsl-ehci.2: USB 2.0 started, EHCI 1.00
<6>usb usb3: configuration #1 chosen from 1 choice
<6>hub 3-0:1.0: USB hub found
<6>hub 3-0:1.0: 1 port detected
<6>Initializing USB Mass Storage driver...
<6>usb 2-1: new full speed USB device using fsl-ehci and address 2
<6>usbcore: registered new interface driver usb-storage
<6>USB Mass Storage support registered.
<6>usb 2-1: configuration #1 chosen from 1 choice
<6>hub 2-1:1.0: USB hub found
<6>hub 2-1:1.0: 4 ports detected
<6>usb 2-1.1: new full speed USB device using fsl-ehci and address 3
<6>kjournald starting. Commit interval 5 seconds
<4>EXT3-fs warning: maximal mount count reached, running e2fsck is recommended
<6>EXT3 FS on sda3, internal journal
<6>EXT3-fs: recovery complete.
<6>EXT3-fs: mounted filesystem with ordered data mode.
<6>usb 2-1.1: configuration #1 chosen from 1 choice
<6>eth0: Freescale FEC PHY driver [Generic PHY] (mii_bus:phy_addr=0:00, irq=-1)
<4>expio_set_type_irq IRQF_TRIGGER_LOW
<6>XANTHUS: ks_update_link_status
<6>usb 2-1.2: new full speed USB device using fsl-ehci and address 4
<6>usb 2-1.2: configuration #1 chosen from 1 choice
<6>usb 2-1.3: new full speed USB device using fsl-ehci and address 5
<6>usb 2-1.3: configuration #1 chosen from 1 choice
<6>PHY: 0:00 - Link is Up - 100/Full
<6>eth0: Freescale FEC PHY driver [Generic PHY] (mii_bus:phy_addr=0:00, irq=-1)
<6>bonding: bond0: making interface eth0 the new active one.
<6>bonding: bond0: first active interface up!
<6>bonding: bond0: enslaving eth0 as an active interface with an up link.
<6>ks_net_stop
<6>ks8851_mll ks8851_mll.0: eth1: shutting down
<4>expio_set_type_irq IRQF_TRIGGER_LOW
<6>XANTHUS: ks_update_link_status
<6>XANTHUS: KS8851 mac(00:1d:9e:00:17:2e)
<6>bonding: bond0: enslaving eth1 as a backup interface with a down link.
<6>kjournald starting. Commit interval 5 seconds
<4>EXT3-fs warning: maximal mount count reached, running e2fsck is recommended
<6>EXT3 FS on sda2, internal journal
<6>EXT3-fs: recovery complete.
<6>EXT3-fs: mounted filesystem with ordered data mode.
<6>kjournald starting. Commit interval 5 seconds
<4>EXT3-fs warning: maximal mount count reached, running e2fsck is recommended
<6>EXT3 FS on sda4, internal journal
<6>EXT3-fs: recovery complete.
<6>EXT3-fs: mounted filesystem with ordered data mode.
<6>PHY: 0:00 - Link is Up - 100/Full
<6>usbcore: registered new interface driver snd-usb-audio
<4>axiodrv: module license 'Proprietary' taints kernel.
<4>Disabling lock debugging due to kernel taint
<6>io: registered with major 250 and delay 1000
^ permalink raw reply
* Re: [PATCH 1/2] mmc: host: arasan: Add addition of-arasan quirks and add IOMMU support.
From: Arnd Bergmann @ 2014-12-15 21:27 UTC (permalink / raw)
To: linuxppc-dev
Cc: devicetree, Suman Tripathi, jcm, anton, linux-mmc, chris, patches,
ddutile, linux-arm-kernel
In-Reply-To: <1418662867-9210-2-git-send-email-stripathi@apm.com>
On Monday 15 December 2014 22:31:06 Suman Tripathi wrote:
> @@ -162,6 +206,16 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
> goto clk_dis_ahb;
> }
>
> +#if defined(CONFIG_IOMMU_SUPPORT)
> + sdhci_arasan->domain = iommu_domain_alloc(&amba_bustype);
> + if (!sdhci_arasan->domain) {
> + dev_err(&pdev->dev, "Unable to allocate iommu domain\n");
> + return PTR_ERR(sdhci_arasan->domain);
> + }
> +
> + iommu_attach_device(sdhci_arasan->domain, &pdev->dev);
> +#endif
> +
>
Device drivers should never care about the implementation details
of the iommu. Please change the code to use the regular dma_map_*
interfaces that will work both with and without IOMMU.
Arnd
^ permalink raw reply
* Re: PROBLEM: USB isochronous urb leak on EHCI driver
From: Greg KH @ 2014-12-15 21:48 UTC (permalink / raw)
To: Michael Tessier; +Cc: linuxppc-dev@lists.ozlabs.org, linux-usb@vger.kernel.org
In-Reply-To: <66A26A9AA227D947AF088537F041526E1FF44F@VSVR-EX10-MB1.pocatec.com>
On Mon, Dec 15, 2014 at 08:53:20PM +0000, Michael Tessier wrote:
> <5>Linux version 2.6.31-770-g0e46b52-0897 (michael.tessier@vsvr-compile-01.pocatec.com) (gcc version 4.1.2) #12 PREEMPT Mon Nov 24 18:34:19 EST 2014
That is a _very_ old and obsolete kernel version, you need to get
support from the company that is forcing you to stay on that version, as
you are paying them for this.
There is nothing the community can do with a kernel version like this,
sorry.
best of luck,
greg k-h
^ 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