* Re: [PATCH v2 2/2] powerpc/44x: Add more changes for APM821XX EMAC driver
From: Stefan Roese @ 2012-03-05 7:41 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Duc Dang, linux-kernel, Paul Mackerras, netdev, David Miller
In-Reply-To: <1330920224-3006-1-git-send-email-dhdang@apm.com>
On Monday 05 March 2012 05:03:44 Duc Dang wrote:
> This patch includes:
>
> Configure EMAC PHY clock source (clock from PHY or internal clock).
>
> Do not advertise PHY half duplex capability as APM821XX EMAC does not
> support half duplex mode.
>
> Add changes to support configuring jumbo frame for APM821XX EMAC.
>
> Signed-off-by: Duc Dang <dhdang@apm.com>
> ---
> v2:
> Fix coding style problems.
>
> drivers/net/ethernet/ibm/emac/core.c | 26 +++++++++++++++++++++++++-
> drivers/net/ethernet/ibm/emac/core.h | 13 +++++++++++--
> drivers/net/ethernet/ibm/emac/emac.h | 5 ++++-
> 3 files changed, 40 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/ibm/emac/core.c
> b/drivers/net/ethernet/ibm/emac/core.c index 2abce96..ad671c5 100644
> --- a/drivers/net/ethernet/ibm/emac/core.c
> +++ b/drivers/net/ethernet/ibm/emac/core.c
> @@ -434,6 +434,11 @@ static inline u32 emac_iff2rmr(struct net_device
> *ndev) else if (!netdev_mc_empty(ndev))
> r |= EMAC_RMR_MAE;
>
> + if (emac_has_feature(dev, EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE)) {
> + r &= ~EMAC4_RMR_MJS_MASK;
> + r |= EMAC4_RMR_MJS(ndev->mtu);
> + }
> +
> return r;
> }
>
> @@ -965,6 +970,7 @@ static int emac_resize_rx_ring(struct emac_instance
> *dev, int new_mtu) int rx_sync_size = emac_rx_sync_size(new_mtu);
> int rx_skb_size = emac_rx_skb_size(new_mtu);
> int i, ret = 0;
> + int mr1_jumbo_bit_change = 0;
>
> mutex_lock(&dev->link_lock);
> emac_netif_stop(dev);
> @@ -1013,7 +1019,14 @@ static int emac_resize_rx_ring(struct emac_instance
> *dev, int new_mtu) }
> skip:
> /* Check if we need to change "Jumbo" bit in MR1 */
> - if ((new_mtu > ETH_DATA_LEN) ^ (dev->ndev->mtu > ETH_DATA_LEN)) {
> + if (emac_has_feature(dev, EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE))
> + mr1_jumbo_bit_change = (new_mtu > ETH_DATA_LEN) ||
> + (dev->ndev->mtu > ETH_DATA_LEN);
> + else
> + mr1_jumbo_bit_change = (new_mtu > ETH_DATA_LEN) ^
> + (dev->ndev->mtu > ETH_DATA_LEN);
> +
> + if (mr1_jumbo_bit_change) {
> /* This is to prevent starting RX channel in emac_rx_enable()
*/
> set_bit(MAL_COMMAC_RX_STOPPED, &dev->commac.flags);
>
> @@ -2471,6 +2484,7 @@ static int __devinit emac_init_phy(struct
> emac_instance *dev)
>
> /* Disable any PHY features not supported by the platform */
> dev->phy.def->features &= ~dev->phy_feat_exc;
> + dev->phy.features &= ~dev->phy_feat_exc;
>
> /* Setup initial link parameters */
> if (dev->phy.features & SUPPORTED_Autoneg) {
> @@ -2568,6 +2582,10 @@ static int __devinit emac_init_config(struct
> emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-405ex") ||
> of_device_is_compatible(np, "ibm,emac-405exr"))
> dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
> + if (of_device_is_compatible(np, "ibm,emac-apm821xx"))
> + dev->features |= (EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE
|
> + EMAC_FTR_APM821XX_NO_HALF_DUPLEX |
> + EMAC_FTR_460EX_PHY_CLK_FIX);
Nitpick: Parentheses for multi line statement please.
> } else if (of_device_is_compatible(np, "ibm,emac4")) {
> dev->features |= EMAC_FTR_EMAC4;
> if (of_device_is_compatible(np, "ibm,emac-440gx"))
> @@ -2818,6 +2836,12 @@ static int __devinit emac_probe(struct
> platform_device *ofdev) dev->stop_timeout = STOP_TIMEOUT_100;
> INIT_DELAYED_WORK(&dev->link_work, emac_link_timer);
>
> + /* Some SoCs like APM821xx does not support Half Duplex mode. */
> + if (emac_has_feature(dev, EMAC_FTR_APM821XX_NO_HALF_DUPLEX))
> + dev->phy_feat_exc = (SUPPORTED_1000baseT_Half |
> + SUPPORTED_100baseT_Half |
> + SUPPORTED_10baseT_Half);
> +
Nitpick: Parentheses for multi line statement please.
> /* Find PHY if any */
> err = emac_init_phy(dev);
> if (err != 0)
> diff --git a/drivers/net/ethernet/ibm/emac/core.h
> b/drivers/net/ethernet/ibm/emac/core.h index fa3ec57..9dea85a 100644
> --- a/drivers/net/ethernet/ibm/emac/core.h
> +++ b/drivers/net/ethernet/ibm/emac/core.h
> @@ -325,7 +325,14 @@ struct emac_instance {
> * Set if we need phy clock workaround for 460ex or 460gt
> */
> #define EMAC_FTR_460EX_PHY_CLK_FIX 0x00000400
> -
> +/*
> + * APM821xx requires Jumbo frame size set explicitly
> + */
> +#define EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE 0x00000800
> +/*
> + * APM821xx does not support Half Duplex mode
> + */
> +#define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000
>
> /* Right now, we don't quite handle the always/possible masks on the
> * most optimal way as we don't have a way to say something like
> @@ -353,7 +360,9 @@ enum {
> EMAC_FTR_NO_FLOW_CONTROL_40x |
> #endif
> EMAC_FTR_460EX_PHY_CLK_FIX |
> - EMAC_FTR_440EP_PHY_CLK_FIX,
> + EMAC_FTR_440EP_PHY_CLK_FIX |
> + EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE |
> + EMAC_FTR_APM821XX_NO_HALF_DUPLEX,
> };
>
> static inline int emac_has_feature(struct emac_instance *dev,
> diff --git a/drivers/net/ethernet/ibm/emac/emac.h
> b/drivers/net/ethernet/ibm/emac/emac.h index 1568278..36bcd69 100644
> --- a/drivers/net/ethernet/ibm/emac/emac.h
> +++ b/drivers/net/ethernet/ibm/emac/emac.h
> @@ -212,7 +212,10 @@ struct emac_regs {
> #define EMAC4_RMR_RFAF_64_1024 0x00000006
> #define EMAC4_RMR_RFAF_128_2048 0x00000007
> #define EMAC4_RMR_BASE EMAC4_RMR_RFAF_128_2048
> -
> +#if defined(CONFIG_APM821xx)
> +#define EMAC4_RMR_MJS_MASK 0x0001fff8
> +#define EMAC4_RMR_MJS(s) (((s) << 3) & EMAC4_RMR_MJS_MASK)
> +#endif
Is this "#if defined" really needed? If not, I suggest you drop it.
Thanks,
Stefan
^ permalink raw reply
* Re: [PATCH v2 2/2] powerpc/44x: Add more changes for APM821XX EMAC driver
From: Duc Dang @ 2012-03-05 8:45 UTC (permalink / raw)
To: Stefan Roese
Cc: linux-kernel, Paul Mackerras, netdev, linuxppc-dev, David Miller
In-Reply-To: <201203050841.57291.sr@denx.de>
[-- Attachment #1: Type: text/plain, Size: 6689 bytes --]
Thanks, Stefan.
Please see my answer bellow.
Regards,
Duc Dang.
On Mon, Mar 5, 2012 at 2:41 PM, Stefan Roese <sr@denx.de> wrote:
> On Monday 05 March 2012 05:03:44 Duc Dang wrote:
> > This patch includes:
> >
> > Configure EMAC PHY clock source (clock from PHY or internal clock).
> >
> > Do not advertise PHY half duplex capability as APM821XX EMAC does not
> > support half duplex mode.
> >
> > Add changes to support configuring jumbo frame for APM821XX EMAC.
> >
> > Signed-off-by: Duc Dang <dhdang@apm.com>
> > ---
> > v2:
> > Fix coding style problems.
> >
> > drivers/net/ethernet/ibm/emac/core.c | 26 +++++++++++++++++++++++++-
> > drivers/net/ethernet/ibm/emac/core.h | 13 +++++++++++--
> > drivers/net/ethernet/ibm/emac/emac.h | 5 ++++-
> > 3 files changed, 40 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/ibm/emac/core.c
> > b/drivers/net/ethernet/ibm/emac/core.c index 2abce96..ad671c5 100644
> > --- a/drivers/net/ethernet/ibm/emac/core.c
> > +++ b/drivers/net/ethernet/ibm/emac/core.c
> > @@ -434,6 +434,11 @@ static inline u32 emac_iff2rmr(struct net_device
> > *ndev) else if (!netdev_mc_empty(ndev))
> > r |= EMAC_RMR_MAE;
> >
> > + if (emac_has_feature(dev, EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE)) {
> > + r &= ~EMAC4_RMR_MJS_MASK;
> > + r |= EMAC4_RMR_MJS(ndev->mtu);
> > + }
> > +
> > return r;
> > }
> >
> > @@ -965,6 +970,7 @@ static int emac_resize_rx_ring(struct emac_instance
> > *dev, int new_mtu) int rx_sync_size = emac_rx_sync_size(new_mtu);
> > int rx_skb_size = emac_rx_skb_size(new_mtu);
> > int i, ret = 0;
> > + int mr1_jumbo_bit_change = 0;
> >
> > mutex_lock(&dev->link_lock);
> > emac_netif_stop(dev);
> > @@ -1013,7 +1019,14 @@ static int emac_resize_rx_ring(struct
> emac_instance
> > *dev, int new_mtu) }
> > skip:
> > /* Check if we need to change "Jumbo" bit in MR1 */
> > - if ((new_mtu > ETH_DATA_LEN) ^ (dev->ndev->mtu > ETH_DATA_LEN)) {
> > + if (emac_has_feature(dev, EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE))
> > + mr1_jumbo_bit_change = (new_mtu > ETH_DATA_LEN) ||
> > + (dev->ndev->mtu > ETH_DATA_LEN);
> > + else
> > + mr1_jumbo_bit_change = (new_mtu > ETH_DATA_LEN) ^
> > + (dev->ndev->mtu > ETH_DATA_LEN);
> > +
> > + if (mr1_jumbo_bit_change) {
> > /* This is to prevent starting RX channel in
> emac_rx_enable()
> */
> > set_bit(MAL_COMMAC_RX_STOPPED, &dev->commac.flags);
> >
> > @@ -2471,6 +2484,7 @@ static int __devinit emac_init_phy(struct
> > emac_instance *dev)
> >
> > /* Disable any PHY features not supported by the platform */
> > dev->phy.def->features &= ~dev->phy_feat_exc;
> > + dev->phy.features &= ~dev->phy_feat_exc;
> >
> > /* Setup initial link parameters */
> > if (dev->phy.features & SUPPORTED_Autoneg) {
> > @@ -2568,6 +2582,10 @@ static int __devinit emac_init_config(struct
> > emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-405ex") ||
> > of_device_is_compatible(np, "ibm,emac-405exr"))
> > dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
> > + if (of_device_is_compatible(np, "ibm,emac-apm821xx"))
> > + dev->features |=
> (EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE
> |
> > + EMAC_FTR_APM821XX_NO_HALF_DUPLEX |
> > + EMAC_FTR_460EX_PHY_CLK_FIX);
>
> Nitpick: Parentheses for multi line statement please.
>
[Duc Dang] I wil add parentheses as you suggested.
> } else if (of_device_is_compatible(np, "ibm,emac4")) {
> > dev->features |= EMAC_FTR_EMAC4;
> > if (of_device_is_compatible(np, "ibm,emac-440gx"))
> > @@ -2818,6 +2836,12 @@ static int __devinit emac_probe(struct
> > platform_device *ofdev) dev->stop_timeout = STOP_TIMEOUT_100;
> > INIT_DELAYED_WORK(&dev->link_work, emac_link_timer);
> >
> > + /* Some SoCs like APM821xx does not support Half Duplex mode. */
> > + if (emac_has_feature(dev, EMAC_FTR_APM821XX_NO_HALF_DUPLEX))
> > + dev->phy_feat_exc = (SUPPORTED_1000baseT_Half |
> > + SUPPORTED_100baseT_Half |
> > + SUPPORTED_10baseT_Half);
> > +
>
> Nitpick: Parentheses for multi line statement please.
>
> > /* Find PHY if any */
> > err = emac_init_phy(dev);
> > if (err != 0)
> > diff --git a/drivers/net/ethernet/ibm/emac/core.h
> > b/drivers/net/ethernet/ibm/emac/core.h index fa3ec57..9dea85a 100644
> > --- a/drivers/net/ethernet/ibm/emac/core.h
> > +++ b/drivers/net/ethernet/ibm/emac/core.h
> > @@ -325,7 +325,14 @@ struct emac_instance {
> > * Set if we need phy clock workaround for 460ex or 460gt
> > */
> > #define EMAC_FTR_460EX_PHY_CLK_FIX 0x00000400
> > -
> > +/*
> > + * APM821xx requires Jumbo frame size set explicitly
> > + */
> > +#define EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE 0x00000800
> > +/*
> > + * APM821xx does not support Half Duplex mode
> > + */
> > +#define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000
> >
> > /* Right now, we don't quite handle the always/possible masks on the
> > * most optimal way as we don't have a way to say something like
> > @@ -353,7 +360,9 @@ enum {
> > EMAC_FTR_NO_FLOW_CONTROL_40x |
> > #endif
> > EMAC_FTR_460EX_PHY_CLK_FIX |
> > - EMAC_FTR_440EP_PHY_CLK_FIX,
> > + EMAC_FTR_440EP_PHY_CLK_FIX |
> > + EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE |
> > + EMAC_FTR_APM821XX_NO_HALF_DUPLEX,
> > };
> >
> > static inline int emac_has_feature(struct emac_instance *dev,
> > diff --git a/drivers/net/ethernet/ibm/emac/emac.h
> > b/drivers/net/ethernet/ibm/emac/emac.h index 1568278..36bcd69 100644
> > --- a/drivers/net/ethernet/ibm/emac/emac.h
> > +++ b/drivers/net/ethernet/ibm/emac/emac.h
> > @@ -212,7 +212,10 @@ struct emac_regs {
> > #define EMAC4_RMR_RFAF_64_1024 0x00000006
> > #define EMAC4_RMR_RFAF_128_2048 0x00000007
> > #define EMAC4_RMR_BASE EMAC4_RMR_RFAF_128_2048
> > -
> > +#if defined(CONFIG_APM821xx)
> > +#define EMAC4_RMR_MJS_MASK 0x0001fff8
> > +#define EMAC4_RMR_MJS(s) (((s) << 3) &
> EMAC4_RMR_MJS_MASK)
> > +#endif
>
> Is this "#if defined" really needed? If not, I suggest you drop it.
>
> [Duc Dang] Only APM821XX and later SoCs have this register field, but it
> is no harm to drop the #if defined as 460EX/460GT/405EX have this register
> field as reserved. So I will drop it.
>
> Thanks,
> Stefan
>
[-- Attachment #2: Type: text/html, Size: 8456 bytes --]
^ permalink raw reply
* RE: [PATCH 13/38] KVM: PPC: booke: category E.HV (GS-mode) support
From: Bhushan Bharat-R65777 @ 2012-03-05 9:04 UTC (permalink / raw)
To: Alexander Graf, kvm-ppc@vger.kernel.org
Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org,
kvm@vger.kernel.org
In-Reply-To: <1330474206-14794-14-git-send-email-agraf@suse.de>
> -----Original Message-----
> From: kvm-owner@vger.kernel.org [mailto:kvm-owner@vger.kernel.org] On Beh=
alf Of
> Alexander Graf
> Sent: Wednesday, February 29, 2012 5:40 AM
> To: kvm-ppc@vger.kernel.org
> Cc: kvm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood Scott-B07421
> Subject: [PATCH 13/38] KVM: PPC: booke: category E.HV (GS-mode) support
>=20
> From: Scott Wood <scottwood@freescale.com>
>=20
> Chips such as e500mc that implement category E.HV in Power ISA 2.06
> provide hardware virtualization features, including a new MSR mode for
> guest state. The guest OS can perform many operations without trapping
> into the hypervisor, including transitions to and from guest userspace.
>=20
> Since we can use SRR1[GS] to reliably tell whether an exception came from
> guest state, instead of messing around with IVPR, we use DO_KVM similarly
> to book3s.
>=20
> Current issues include:
> - Machine checks from guest state are not routed to the host handler.
> - The guest can cause a host oops by executing an emulated instruction
> in a page that lacks read permission. Existing e500/4xx support has
> the same problem.
>=20
> Includes work by Ashish Kalra <Ashish.Kalra@freescale.com>,
> Varun Sethi <Varun.Sethi@freescale.com>, and
> Liu Yu <yu.liu@freescale.com>.
>=20
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> [agraf: remove pt_regs usage]
> Signed-off-by: Alexander Graf <agraf@suse.de>
>=20
> ---
>=20
> v1 -> v2:
>=20
> - ESR -> GESR
> ---
> arch/powerpc/include/asm/dbell.h | 1 +
> arch/powerpc/include/asm/kvm_asm.h | 8 +
> arch/powerpc/include/asm/kvm_booke_hv_asm.h | 49 +++
> arch/powerpc/include/asm/kvm_host.h | 19 +-
> arch/powerpc/include/asm/kvm_ppc.h | 3 +
> arch/powerpc/include/asm/mmu-book3e.h | 6 +
> arch/powerpc/include/asm/processor.h | 3 +
> arch/powerpc/include/asm/reg.h | 2 +
> arch/powerpc/include/asm/reg_booke.h | 34 ++
> arch/powerpc/kernel/asm-offsets.c | 15 +-
> arch/powerpc/kernel/head_booke.h | 28 ++-
> arch/powerpc/kvm/Kconfig | 3 +
> arch/powerpc/kvm/booke.c | 309 ++++++++++++---
> arch/powerpc/kvm/booke.h | 24 +-
> arch/powerpc/kvm/booke_emulate.c | 23 +-
> arch/powerpc/kvm/bookehv_interrupts.S | 587 +++++++++++++++++++++=
++++++
> arch/powerpc/kvm/powerpc.c | 5 +
> arch/powerpc/kvm/timing.h | 6 +
> 18 files changed, 1058 insertions(+), 67 deletions(-)
> create mode 100644 arch/powerpc/include/asm/kvm_booke_hv_asm.h
> create mode 100644 arch/powerpc/kvm/bookehv_interrupts.S
>=20
> diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/=
dbell.h
> index efa74ac..d7365b0 100644
> --- a/arch/powerpc/include/asm/dbell.h
> +++ b/arch/powerpc/include/asm/dbell.h
> @@ -19,6 +19,7 @@
>=20
> #define PPC_DBELL_MSG_BRDCAST (0x04000000)
> #define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36))
> +#define PPC_DBELL_LPID(x) ((x) << (63 - 49))
> enum ppc_dbell {
> PPC_DBELL =3D 0, /* doorbell */
> PPC_DBELL_CRIT =3D 1, /* critical doorbell */
> diff --git a/arch/powerpc/include/asm/kvm_asm.h
> b/arch/powerpc/include/asm/kvm_asm.h
> index 7b1f0e0..0978152 100644
> --- a/arch/powerpc/include/asm/kvm_asm.h
> +++ b/arch/powerpc/include/asm/kvm_asm.h
> @@ -48,6 +48,14 @@
> #define BOOKE_INTERRUPT_SPE_FP_DATA 33
> #define BOOKE_INTERRUPT_SPE_FP_ROUND 34
> #define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35
> +#define BOOKE_INTERRUPT_DOORBELL 36
> +#define BOOKE_INTERRUPT_DOORBELL_CRITICAL 37
> +
> +/* booke_hv */
> +#define BOOKE_INTERRUPT_GUEST_DBELL 38
> +#define BOOKE_INTERRUPT_GUEST_DBELL_CRIT 39
> +#define BOOKE_INTERRUPT_HV_SYSCALL 40
> +#define BOOKE_INTERRUPT_HV_PRIV 41
>=20
> /* book3s */
>=20
> diff --git a/arch/powerpc/include/asm/kvm_booke_hv_asm.h
> b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
> new file mode 100644
> index 0000000..30a600f
> --- /dev/null
> +++ b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright 2010-2011 Freescale Semiconductor, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef ASM_KVM_BOOKE_HV_ASM_H
> +#define ASM_KVM_BOOKE_HV_ASM_H
> +
> +#ifdef __ASSEMBLY__
> +
> +/*
> + * All exceptions from guest state must go through KVM
> + * (except for those which are delivered directly to the guest) --
> + * there are no exceptions for which we fall through directly to
> + * the normal host handler.
> + *
> + * Expected inputs (normal exceptions):
> + * SCRATCH0 =3D saved r10
> + * r10 =3D thread struct
> + * r11 =3D appropriate SRR1 variant (currently used as scratch)
> + * r13 =3D saved CR
> + * *(r10 + THREAD_NORMSAVE(0)) =3D saved r11
> + * *(r10 + THREAD_NORMSAVE(2)) =3D saved r13
> + *
> + * Expected inputs (crit/mcheck/debug exceptions):
> + * appropriate SCRATCH =3D saved r8
> + * r8 =3D exception level stack frame
> + * r9 =3D *(r8 + _CCR) =3D saved CR
> + * r11 =3D appropriate SRR1 variant (currently used as scratch)
> + * *(r8 + GPR9) =3D saved r9
> + * *(r8 + GPR10) =3D saved r10 (r10 not yet clobbered)
> + * *(r8 + GPR11) =3D saved r11
> + */
> +.macro DO_KVM intno srr1
> +#ifdef CONFIG_KVM_BOOKE_HV
> +BEGIN_FTR_SECTION
> + mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
> + bf 3, kvmppc_resume_\intno\()_\srr1
> + b kvmppc_handler_\intno\()_\srr1
> +kvmppc_resume_\intno\()_\srr1:
> +END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
> +#endif
> +.endm
> +
> +#endif /*__ASSEMBLY__ */
> +#endif /* ASM_KVM_BOOKE_HV_ASM_H */
> diff --git a/arch/powerpc/include/asm/kvm_host.h
> b/arch/powerpc/include/asm/kvm_host.h
> index 47612cc..ed95f53 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -106,6 +106,8 @@ struct kvm_vcpu_stat {
> u32 dec_exits;
> u32 ext_intr_exits;
> u32 halt_wakeup;
> + u32 dbell_exits;
> + u32 gdbell_exits;
> #ifdef CONFIG_PPC_BOOK3S
> u32 pf_storage;
> u32 pf_instruc;
> @@ -140,6 +142,7 @@ enum kvm_exit_types {
> EMULATED_TLBSX_EXITS,
> EMULATED_TLBWE_EXITS,
> EMULATED_RFI_EXITS,
> + EMULATED_RFCI_EXITS,
> DEC_EXITS,
> EXT_INTR_EXITS,
> HALT_WAKEUP,
> @@ -147,6 +150,8 @@ enum kvm_exit_types {
> FP_UNAVAIL,
> DEBUG_EXITS,
> TIMEINGUEST,
> + DBELL_EXITS,
> + GDBELL_EXITS,
> __NUMBER_OF_KVM_EXIT_TYPES
> };
>=20
> @@ -217,10 +222,10 @@ struct kvm_arch_memory_slot {
> };
>=20
> struct kvm_arch {
> + unsigned int lpid;
> #ifdef CONFIG_KVM_BOOK3S_64_HV
> unsigned long hpt_virt;
> struct revmap_entry *revmap;
> - unsigned int lpid;
> unsigned int host_lpid;
> unsigned long host_lpcr;
> unsigned long sdr1;
> @@ -345,6 +350,17 @@ struct kvm_vcpu_arch {
> u64 vsr[64];
> #endif
>=20
> +#ifdef CONFIG_KVM_BOOKE_HV
> + u32 host_mas4;
> + u32 host_mas6;
> + u32 shadow_epcr;
> + u32 epcr;
> + u32 shadow_msrp;
> + u32 eplc;
> + u32 epsc;
> + u32 oldpir;
> +#endif
> +
> #ifdef CONFIG_PPC_BOOK3S
> /* For Gekko paired singles */
> u32 qpr[32];
> @@ -428,6 +444,7 @@ struct kvm_vcpu_arch {
> ulong queued_esr;
> u32 tlbcfg[4];
> u32 mmucfg;
> + u32 epr;
> #endif
> gpa_t paddr_accessed;
>=20
> diff --git a/arch/powerpc/include/asm/kvm_ppc.h
> b/arch/powerpc/include/asm/kvm_ppc.h
> index 731e920..e709975 100644
> --- a/arch/powerpc/include/asm/kvm_ppc.h
> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> @@ -139,6 +139,9 @@ extern int kvmppc_core_prepare_memory_region(struct k=
vm
> *kvm,
> extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
> struct kvm_userspace_memory_region *mem);
>=20
> +extern int kvmppc_bookehv_init(void);
> +extern void kvmppc_bookehv_exit(void);
> +
> /*
> * Cuts out inst bits with ordering according to spec.
> * That means the leftmost bit is zero. All given bits are included.
> diff --git a/arch/powerpc/include/asm/mmu-book3e.h
> b/arch/powerpc/include/asm/mmu-book3e.h
> index cdb5421..eeabcdb 100644
> --- a/arch/powerpc/include/asm/mmu-book3e.h
> +++ b/arch/powerpc/include/asm/mmu-book3e.h
> @@ -104,6 +104,8 @@
> #define MAS4_TSIZED_MASK 0x00000f80 /* Default TSIZE */
> #define MAS4_TSIZED_SHIFT 7
>=20
> +#define MAS5_SGS 0x80000000
> +
> #define MAS6_SPID0 0x3FFF0000
> #define MAS6_SPID1 0x00007FFE
> #define MAS6_ISIZE(x) MAS1_TSIZE(x)
> @@ -118,6 +120,10 @@
>=20
> #define MAS7_RPN 0xFFFFFFFF
>=20
> +#define MAS8_TGS 0x80000000 /* Guest space */
> +#define MAS8_VF 0x40000000 /* Virtualization Fault */
> +#define MAS8_TLPID 0x000000ff
> +
> /* Bit definitions for MMUCFG */
> #define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
> #define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
> diff --git a/arch/powerpc/include/asm/processor.h
> b/arch/powerpc/include/asm/processor.h
> index b585bff..f64262b 100644
> --- a/arch/powerpc/include/asm/processor.h
> +++ b/arch/powerpc/include/asm/processor.h
> @@ -243,6 +243,9 @@ struct thread_struct {
> #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
> void* kvm_shadow_vcpu; /* KVM internal data */
> #endif /* CONFIG_KVM_BOOK3S_32_HANDLER */
> +#if defined(CONFIG_KVM) && defined(CONFIG_BOOKE)
> + struct kvm_vcpu *kvm_vcpu;
> +#endif
> #ifdef CONFIG_PPC64
> unsigned long dscr;
> int dscr_inherit;
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/re=
g.h
> index 35c9309..67512f3 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -257,7 +257,9 @@
> #define LPCR_LPES_SH 2
> #define LPCR_RMI 0x00000002 /* real mode is cache inhibit */
> #define LPCR_HDICE 0x00000001 /* Hyp Decr enable (HV,PR,EE) */
> +#ifndef SPRN_LPID
> #define SPRN_LPID 0x13F /* Logical Partition Identifier */
> +#endif
> #define LPID_RSVD 0x3ff /* Reserved LPID for partn switching */
> #define SPRN_HMER 0x150 /* Hardware m? error recovery */
> #define SPRN_HMEER 0x151 /* Hardware m? enable error recovery */
> diff --git a/arch/powerpc/include/asm/reg_booke.h
> b/arch/powerpc/include/asm/reg_booke.h
> index 500fe1d..8960afc 100644
> --- a/arch/powerpc/include/asm/reg_booke.h
> +++ b/arch/powerpc/include/asm/reg_booke.h
> @@ -56,17 +56,29 @@
> #define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */
> #define SPRN_EPCR 0x133 /* Embedded Processor Control Register */
> #define SPRN_DBCR2 0x136 /* Debug Control Register 2 */
> +#define SPRN_MSRP 0x137 /* MSR Protect Register */
> #define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */
> #define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */
> #define SPRN_DVC1 0x13E /* Data Value Compare Register 1 */
> #define SPRN_DVC2 0x13F /* Data Value Compare Register 2 */
> +#define SPRN_LPID 0x152 /* Logical Partition ID */
> #define SPRN_MAS8 0x155 /* MMU Assist Register 8 */
> #define SPRN_TLB0PS 0x158 /* TLB 0 Page Size Register */
> #define SPRN_MAS5_MAS6 0x15c /* MMU Assist Register 5 || 6 */
> #define SPRN_MAS8_MAS1 0x15d /* MMU Assist Register 8 || 1 */
> #define SPRN_EPTCFG 0x15e /* Embedded Page Table Config */
> +#define SPRN_GSPRG0 0x170 /* Guest SPRG0 */
> +#define SPRN_GSPRG1 0x171 /* Guest SPRG1 */
> +#define SPRN_GSPRG2 0x172 /* Guest SPRG2 */
> +#define SPRN_GSPRG3 0x173 /* Guest SPRG3 */
> #define SPRN_MAS7_MAS3 0x174 /* MMU Assist Register 7 || 3 */
> #define SPRN_MAS0_MAS1 0x175 /* MMU Assist Register 0 || 1 */
> +#define SPRN_GSRR0 0x17A /* Guest SRR0 */
> +#define SPRN_GSRR1 0x17B /* Guest SRR1 */
> +#define SPRN_GEPR 0x17C /* Guest EPR */
> +#define SPRN_GDEAR 0x17D /* Guest DEAR */
> +#define SPRN_GPIR 0x17E /* Guest PIR */
> +#define SPRN_GESR 0x17F /* Guest Exception Syndrome Register */
> #define SPRN_IVOR0 0x190 /* Interrupt Vector Offset Register 0 */
> #define SPRN_IVOR1 0x191 /* Interrupt Vector Offset Register 1 */
> #define SPRN_IVOR2 0x192 /* Interrupt Vector Offset Register 2 */
> @@ -87,6 +99,13 @@
> #define SPRN_IVOR39 0x1B1 /* Interrupt Vector Offset Register 39 */
> #define SPRN_IVOR40 0x1B2 /* Interrupt Vector Offset Register 40 */
> #define SPRN_IVOR41 0x1B3 /* Interrupt Vector Offset Register 41 */
> +#define SPRN_GIVOR2 0x1B8 /* Guest IVOR2 */
> +#define SPRN_GIVOR3 0x1B9 /* Guest IVOR3 */
> +#define SPRN_GIVOR4 0x1BA /* Guest IVOR4 */
> +#define SPRN_GIVOR8 0x1BB /* Guest IVOR8 */
> +#define SPRN_GIVOR13 0x1BC /* Guest IVOR13 */
> +#define SPRN_GIVOR14 0x1BD /* Guest IVOR14 */
> +#define SPRN_GIVPR 0x1BF /* Guest IVPR */
> #define SPRN_SPEFSCR 0x200 /* SPE & Embedded FP Status & Control */
> #define SPRN_BBEAR 0x201 /* Branch Buffer Entry Address Register */
> #define SPRN_BBTAR 0x202 /* Branch Buffer Target Address Register */
> @@ -239,6 +258,10 @@
> #define MCSR_LDG 0x00002000UL /* Guarded Load */
> #define MCSR_TLBSYNC 0x00000002UL /* Multiple tlbsyncs detected */
> #define MCSR_BSL2_ERR 0x00000001UL /* Backside L2 cache error */
> +
> +#define MSRP_UCLEP 0x04000000 /* Protect MSR[UCLE] */
> +#define MSRP_DEP 0x00000200 /* Protect MSR[DE] */
> +#define MSRP_PMMP 0x00000004 /* Protect MSR[PMM] */
> #endif
>=20
> #ifdef CONFIG_E200
> @@ -593,6 +616,17 @@
> #define SPRN_EPCR_DMIUH 0x00400000 /* Disable MAS Interrupt updates
> * for hypervisor */
>=20
> +/* Bit definitions for EPLC/EPSC */
> +#define EPC_EPR 0x80000000 /* 1 =3D user, 0 =3D kernel */
> +#define EPC_EPR_SHIFT 31
> +#define EPC_EAS 0x40000000 /* Address Space */
> +#define EPC_EAS_SHIFT 30
> +#define EPC_EGS 0x20000000 /* 1 =3D guest, 0 =3D hypervisor */
> +#define EPC_EGS_SHIFT 29
> +#define EPC_ELPID 0x00ff0000
> +#define EPC_ELPID_SHIFT 16
> +#define EPC_EPID 0x00003fff
> +#define EPC_EPID_SHIFT 0
>=20
> /*
> * The IBM-403 is an even more odd special case, as it is much
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-
> offsets.c
> index 8e0db0b..a24f2c0 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -119,6 +119,9 @@ int main(void)
> #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
> DEFINE(THREAD_KVM_SVCPU, offsetof(struct thread_struct, kvm_shadow_vcpu=
));
> #endif
> +#ifdef CONFIG_KVM_BOOKE_HV
> + DEFINE(THREAD_KVM_VCPU, offsetof(struct thread_struct, kvm_vcpu));
> +#endif
>=20
> DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
> DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
> @@ -401,6 +404,7 @@ int main(void)
> #ifdef CONFIG_KVM
> DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
> DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
> + DEFINE(VCPU_GUEST_PID, offsetof(struct kvm_vcpu, arch.pid));
> DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
> DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave));
> DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fpr));
> @@ -443,9 +447,11 @@ int main(void)
> DEFINE(VCPU_SHARED_MAS4, offsetof(struct kvm_vcpu_arch_shared, mas4));
> DEFINE(VCPU_SHARED_MAS6, offsetof(struct kvm_vcpu_arch_shared, mas6));
>=20
> + DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
> + DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid));
> +
> /* book3s */
> #ifdef CONFIG_KVM_BOOK3S_64_HV
> - DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid));
> DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1));
> DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid));
> DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
> @@ -460,7 +466,6 @@ int main(void)
> DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
> #endif
> #ifdef CONFIG_PPC_BOOK3S
> - DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
> DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
> DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
> DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
> @@ -611,6 +616,12 @@ int main(void)
> DEFINE(VCPU_HOST_SPEFSCR, offsetof(struct kvm_vcpu, arch.host_spefscr))=
;
> #endif
>=20
> +#ifdef CONFIG_KVM_BOOKE_HV
> + DEFINE(VCPU_HOST_MAS4, offsetof(struct kvm_vcpu, arch.host_mas4));
> + DEFINE(VCPU_HOST_MAS6, offsetof(struct kvm_vcpu, arch.host_mas6));
> + DEFINE(VCPU_EPLC, offsetof(struct kvm_vcpu, arch.eplc));
> +#endif
> +
> #ifdef CONFIG_KVM_EXIT_TIMING
> DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
> arch.timing_exit.tv32.tbu));
> diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_=
booke.h
> index 06ab353..b87c335 100644
> --- a/arch/powerpc/kernel/head_booke.h
> +++ b/arch/powerpc/kernel/head_booke.h
> @@ -3,6 +3,7 @@
>=20
> #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
> #include <asm/kvm_asm.h>
> +#include <asm/kvm_booke_hv_asm.h>
>=20
> /*
> * Macros used for common Book-e exception handling
> @@ -36,8 +37,9 @@
> stw r11, THREAD_NORMSAVE(0)(r10); \
> stw r13, THREAD_NORMSAVE(2)(r10); \
> mfcr r13; /* save CR in r13 for now */\
> - mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
> - andi. r11,r11,MSR_PR; \
> + mfspr r11, SPRN_SRR1; \
> + DO_KVM BOOKE_INTERRUPT_##intno SPRN_SRR1; \
> + andi. r11, r11, MSR_PR; /* check whether user or kernel */\
> mr r11, r1; \
> beq 1f; \
> /* if from user, start at top of this thread's kernel stack */ \
> @@ -123,8 +125,9 @@
> stw r10,GPR10(r8); \
> stw r11,GPR11(r8); \
> stw r9,_CCR(r8); /* save CR on stack */\
> - mfspr r10,exc_level_srr1; /* check whether user or kernel */\
> - andi. r10,r10,MSR_PR; \
> + mfspr r11,exc_level_srr1; /* check whether user or kernel */\
> + DO_KVM BOOKE_INTERRUPT_##intno exc_level_srr1; \
> + andi. r11,r11,MSR_PR; \
> mfspr r11,SPRN_SPRG_THREAD; /* if from user, start at top of */\
> lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
> addi r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame */\
> @@ -173,6 +176,23 @@
> SPRN_MCSRR0, SPRN_MCSRR1)
>=20
> /*
> + * Guest Doorbell -- this is a bit odd in that uses GSRR0/1 despite
> + * being delivered to the host. This exception can only happen
> + * inside a KVM guest -- so we just handle up to the DO_KVM rather
> + * than try to fit this into one of the existing prolog macros.
> + */
> +#define GUEST_DOORBELL_EXCEPTION \
> + START_EXCEPTION(GuestDoorbell); \
> + mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \
> + mfspr r10, SPRN_SPRG_THREAD; \
> + stw r11, THREAD_NORMSAVE(0)(r10); \
> + mfspr r11, SPRN_SRR1; \
> + stw r13, THREAD_NORMSAVE(2)(r10); \
> + mfcr r13; /* save CR in r13 for now */\
> + DO_KVM BOOKE_INTERRUPT_GUEST_DBELL SPRN_GSRR1; \
> + trap
> +
> +/*
> * Exception vectors.
> */
> #define START_EXCEPTION(label) \
> diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
> index 8f64709..2c33cd3 100644
> --- a/arch/powerpc/kvm/Kconfig
> +++ b/arch/powerpc/kvm/Kconfig
> @@ -90,6 +90,9 @@ config KVM_BOOK3S_64_PR
> depends on KVM_BOOK3S_64 && !KVM_BOOK3S_64_HV
> select KVM_BOOK3S_PR
>=20
> +config KVM_BOOKE_HV
> + bool
> +
> config KVM_440
> bool "KVM support for PowerPC 440 processors"
> depends on EXPERIMENTAL && 44x
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 2ee9bae..75dbaeb 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -17,6 +17,8 @@
> *
> * Authors: Hollis Blanchard <hollisb@us.ibm.com>
> * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
> + * Scott Wood <scottwood@freescale.com>
> + * Varun Sethi <varun.sethi@freescale.com>
> */
>=20
> #include <linux/errno.h>
> @@ -30,9 +32,12 @@
> #include <asm/cputable.h>
> #include <asm/uaccess.h>
> #include <asm/kvm_ppc.h>
> -#include "timing.h"
> #include <asm/cacheflush.h>
> +#include <asm/dbell.h>
> +#include <asm/hw_irq.h>
> +#include <asm/irq.h>
>=20
> +#include "timing.h"
> #include "booke.h"
>=20
> unsigned long kvmppc_booke_handlers;
> @@ -55,6 +60,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] =3D {
> { "dec", VCPU_STAT(dec_exits) },
> { "ext_intr", VCPU_STAT(ext_intr_exits) },
> { "halt_wakeup", VCPU_STAT(halt_wakeup) },
> + { "doorbell", VCPU_STAT(dbell_exits) },
> + { "guest doorbell", VCPU_STAT(gdbell_exits) },
> { NULL }
> };
>=20
> @@ -121,6 +128,10 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_m=
sr)
> {
> u32 old_msr =3D vcpu->arch.shared->msr;
>=20
> +#ifdef CONFIG_KVM_BOOKE_HV
> + new_msr |=3D MSR_GS;
> +#endif
> +
> vcpu->arch.shared->msr =3D new_msr;
>=20
> kvmppc_mmu_msr_notify(vcpu, old_msr);
> @@ -195,6 +206,75 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *v=
cpu,
> clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions)=
;
> }
>=20
> +static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32=
srr1)
> +{
> +#ifdef CONFIG_KVM_BOOKE_HV
> + mtspr(SPRN_GSRR0, srr0);
> + mtspr(SPRN_GSRR1, srr1);
> +#else
> + vcpu->arch.shared->srr0 =3D srr0;
> + vcpu->arch.shared->srr1 =3D srr1;
> +#endif
> +}
> +
> +static void set_guest_csrr(struct kvm_vcpu *vcpu, unsigned long srr0, u3=
2 srr1)
> +{
> + vcpu->arch.csrr0 =3D srr0;
> + vcpu->arch.csrr1 =3D srr1;
> +}
> +
> +static void set_guest_dsrr(struct kvm_vcpu *vcpu, unsigned long srr0, u3=
2 srr1)
> +{
> + if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC)) {
> + vcpu->arch.dsrr0 =3D srr0;
> + vcpu->arch.dsrr1 =3D srr1;
> + } else {
> + set_guest_csrr(vcpu, srr0, srr1);
> + }
> +}
> +
> +static void set_guest_mcsrr(struct kvm_vcpu *vcpu, unsigned long srr0, u=
32
> srr1)
> +{
> + vcpu->arch.mcsrr0 =3D srr0;
> + vcpu->arch.mcsrr1 =3D srr1;
> +}
> +
> +static unsigned long get_guest_dear(struct kvm_vcpu *vcpu)
> +{
> +#ifdef CONFIG_KVM_BOOKE_HV
> + return mfspr(SPRN_GDEAR);
> +#else
> + return vcpu->arch.shared->dar;
> +#endif
> +}
> +
> +static void set_guest_dear(struct kvm_vcpu *vcpu, unsigned long dear)
> +{
> +#ifdef CONFIG_KVM_BOOKE_HV
> + mtspr(SPRN_GDEAR, dear);
> +#else
> + vcpu->arch.shared->dar =3D dear;
> +#endif
> +}
> +
> +static unsigned long get_guest_esr(struct kvm_vcpu *vcpu)
> +{
> +#ifdef CONFIG_KVM_BOOKE_HV
> + return mfspr(SPRN_GESR);
> +#else
> + return vcpu->arch.shared->esr;
> +#endif
> +}
> +
> +static void set_guest_esr(struct kvm_vcpu *vcpu, u32 esr)
> +{
> +#ifdef CONFIG_KVM_BOOKE_HV
> + mtspr(SPRN_GESR, esr);
> +#else
> + vcpu->arch.shared->esr =3D esr;
> +#endif
> +}
> +
> /* Deliver the interrupt of the corresponding priority, if possible. */
> static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
> unsigned int priority)
> @@ -206,6 +286,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vc=
pu
> *vcpu,
> ulong crit_r1 =3D kvmppc_get_gpr(vcpu, 1);
> bool crit;
> bool keep_irq =3D false;
> + enum int_class int_class;
>=20
> /* Truncate crit indicators in 32 bit mode */
> if (!(vcpu->arch.shared->msr & MSR_SF)) {
> @@ -241,16 +322,20 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_=
vcpu
> *vcpu,
> case BOOKE_IRQPRIO_AP_UNAVAIL:
> case BOOKE_IRQPRIO_ALIGNMENT:
> allowed =3D 1;
> - msr_mask =3D MSR_CE|MSR_ME|MSR_DE;
> + msr_mask =3D MSR_GS | MSR_CE | MSR_ME | MSR_DE;
> + int_class =3D INT_CLASS_NONCRIT;
> break;
> case BOOKE_IRQPRIO_CRITICAL:
> - case BOOKE_IRQPRIO_WATCHDOG:
> allowed =3D vcpu->arch.shared->msr & MSR_CE;
> - msr_mask =3D MSR_ME;
> + allowed =3D allowed && !crit;
> + msr_mask =3D MSR_GS | MSR_ME;
> + int_class =3D INT_CLASS_CRIT;
> break;
> case BOOKE_IRQPRIO_MACHINE_CHECK:
> allowed =3D vcpu->arch.shared->msr & MSR_ME;
> - msr_mask =3D 0;
> + allowed =3D allowed && !crit;
> + msr_mask =3D MSR_GS;
> + int_class =3D INT_CLASS_MC;
> break;
> case BOOKE_IRQPRIO_DECREMENTER:
> case BOOKE_IRQPRIO_FIT:
> @@ -259,28 +344,62 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_=
vcpu
> *vcpu,
> case BOOKE_IRQPRIO_EXTERNAL:
> allowed =3D vcpu->arch.shared->msr & MSR_EE;
> allowed =3D allowed && !crit;
> - msr_mask =3D MSR_CE|MSR_ME|MSR_DE;
> + msr_mask =3D MSR_GS | MSR_CE | MSR_ME | MSR_DE;
> + int_class =3D INT_CLASS_NONCRIT;
> break;
> case BOOKE_IRQPRIO_DEBUG:
> allowed =3D vcpu->arch.shared->msr & MSR_DE;
> - msr_mask =3D MSR_ME;
> + allowed =3D allowed && !crit;
> + msr_mask =3D MSR_GS | MSR_ME;
> + int_class =3D INT_CLASS_CRIT;
> break;
> }
>=20
> if (allowed) {
> - vcpu->arch.shared->srr0 =3D vcpu->arch.pc;
> - vcpu->arch.shared->srr1 =3D vcpu->arch.shared->msr;
> + switch (int_class) {
> + case INT_CLASS_NONCRIT:
> + set_guest_srr(vcpu, vcpu->arch.pc,
> + vcpu->arch.shared->msr);
> + break;
> + case INT_CLASS_CRIT:
> + set_guest_csrr(vcpu, vcpu->arch.pc,
> + vcpu->arch.shared->msr);
> + break;
> + case INT_CLASS_DBG:
> + set_guest_dsrr(vcpu, vcpu->arch.pc,
> + vcpu->arch.shared->msr);
> + break;
> + case INT_CLASS_MC:
> + set_guest_mcsrr(vcpu, vcpu->arch.pc,
> + vcpu->arch.shared->msr);
> + break;
> + }
> +
> vcpu->arch.pc =3D vcpu->arch.ivpr | vcpu->arch.ivor[priority];
> if (update_esr =3D=3D true)
> - vcpu->arch.shared->esr =3D vcpu->arch.queued_esr;
> + set_guest_esr(vcpu, vcpu->arch.queued_esr);
> if (update_dear =3D=3D true)
> - vcpu->arch.shared->dar =3D vcpu->arch.queued_dear;
> + set_guest_dear(vcpu, vcpu->arch.queued_dear);
> kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
>=20
> if (!keep_irq)
> clear_bit(priority, &vcpu->arch.pending_exceptions);
> }
>=20
> +#ifdef CONFIG_KVM_BOOKE_HV
> + /*
> + * If an interrupt is pending but masked, raise a guest doorbell
> + * so that we are notified when the guest enables the relevant
> + * MSR bit.
> + */
> + if (vcpu->arch.pending_exceptions & BOOKE_IRQMASK_EE)
> + kvmppc_set_pending_interrupt(vcpu, INT_CLASS_NONCRIT);
> + if (vcpu->arch.pending_exceptions & BOOKE_IRQMASK_CE)
> + kvmppc_set_pending_interrupt(vcpu, INT_CLASS_CRIT);
> + if (vcpu->arch.pending_exceptions & BOOKE_IRQPRIO_MACHINE_CHECK)
> + kvmppc_set_pending_interrupt(vcpu, INT_CLASS_MC);
> +#endif
> +
> return allowed;
> }
>=20
> @@ -344,6 +463,11 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct
> kvm_vcpu *vcpu)
> return -EINVAL;
> }
>=20
> + if (!current->thread.kvm_vcpu) {
> + WARN(1, "no vcpu\n");
> + return -EPERM;
> + }
> +
> local_irq_disable();
>=20
> kvmppc_core_prepare_to_enter(vcpu);
> @@ -363,6 +487,38 @@ out:
> return ret;
> }
>=20
> +static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
> +{
> + enum emulation_result er;
> +
> + er =3D kvmppc_emulate_instruction(run, vcpu);
> + switch (er) {
> + case EMULATE_DONE:
> + /* don't overwrite subtypes, just account kvm_stats */
> + kvmppc_account_exit_stat(vcpu, EMULATED_INST_EXITS);
> + /* Future optimization: only reload non-volatiles if
> + * they were actually modified by emulation. */
> + return RESUME_GUEST_NV;
> +
> + case EMULATE_DO_DCR:
> + run->exit_reason =3D KVM_EXIT_DCR;
> + return RESUME_HOST;
> +
> + case EMULATE_FAIL:
> + /* XXX Deliver Program interrupt to guest. */
> + printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
> + __func__, vcpu->arch.pc, vcpu->arch.last_inst);
> + /* For debugging, encode the failing instruction and
> + * report it to userspace. */
> + run->hw.hardware_exit_reason =3D ~0ULL << 32;
> + run->hw.hardware_exit_reason |=3D vcpu->arch.last_inst;
> + return RESUME_HOST;
> +
> + default:
> + BUG();
> + }
> +}
> +
> /**
> * kvmppc_handle_exit
> *
> @@ -371,12 +527,30 @@ out:
> int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
> unsigned int exit_nr)
> {
> - enum emulation_result er;
> int r =3D RESUME_HOST;
>=20
> /* update before a new last_exit_type is rewritten */
> kvmppc_update_timing_stats(vcpu);
>=20
> + switch (exit_nr) {
> + case BOOKE_INTERRUPT_EXTERNAL:
> + do_IRQ(current->thread.regs);
> + break;
> +
> + case BOOKE_INTERRUPT_DECREMENTER:
> + timer_interrupt(current->thread.regs);
> + break;
> +
> +#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3E_64)
> + case BOOKE_INTERRUPT_DOORBELL:
> + doorbell_exception(current->thread.regs);
> + break;
> +#endif
> + case BOOKE_INTERRUPT_MACHINE_CHECK:
> + /* FIXME */
> + break;
> + }
> +
> local_irq_enable();
>=20
> run->exit_reason =3D KVM_EXIT_UNKNOWN;
> @@ -384,30 +558,56 @@ int kvmppc_handle_exit(struct kvm_run *run, struct
> kvm_vcpu *vcpu,
>=20
> switch (exit_nr) {
> case BOOKE_INTERRUPT_MACHINE_CHECK:
> - printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR));
> - kvmppc_dump_vcpu(vcpu);
> - r =3D RESUME_HOST;
> + kvm_resched(vcpu);
> + r =3D RESUME_GUEST;
> break;
>=20
> case BOOKE_INTERRUPT_EXTERNAL:
> kvmppc_account_exit(vcpu, EXT_INTR_EXITS);
> - if (need_resched())
> - cond_resched();
> + kvm_resched(vcpu);
> r =3D RESUME_GUEST;
> break;
>=20
> case BOOKE_INTERRUPT_DECREMENTER:
> - /* Since we switched IVPR back to the host's value, the host
> - * handled this interrupt the moment we enabled interrupts.
> - * Now we just offer it a chance to reschedule the guest. */
> kvmppc_account_exit(vcpu, DEC_EXITS);
> - if (need_resched())
> - cond_resched();
> + kvm_resched(vcpu);
> r =3D RESUME_GUEST;
> break;
>=20
> + case BOOKE_INTERRUPT_DOORBELL:
> + kvmppc_account_exit(vcpu, DBELL_EXITS);
> + kvm_resched(vcpu);
> + r =3D RESUME_GUEST;
> + break;
> +
> + case BOOKE_INTERRUPT_GUEST_DBELL_CRIT:
> + kvmppc_account_exit(vcpu, GDBELL_EXITS);
> +
> + /*
> + * We are here because there is a pending guest interrupt
> + * which could not be delivered as MSR_CE or MSR_ME was not
> + * set. Once we break from here we will retry delivery.
> + */
> + r =3D RESUME_GUEST;
> + break;
> +
> + case BOOKE_INTERRUPT_GUEST_DBELL:
> + kvmppc_account_exit(vcpu, GDBELL_EXITS);
> +
> + /*
> + * We are here because there is a pending guest interrupt
> + * which could not be delivered as MSR_EE was not set. Once
> + * we break from here we will retry delivery.
> + */
> + r =3D RESUME_GUEST;
> + break;
> +
> + case BOOKE_INTERRUPT_HV_PRIV:
> + r =3D emulation_exit(run, vcpu);
> + break;
> +
> case BOOKE_INTERRUPT_PROGRAM:
> - if (vcpu->arch.shared->msr & MSR_PR) {
> + if (vcpu->arch.shared->msr & (MSR_PR | MSR_GS)) {
> /* Program traps generated by user-level software must be
> handled
> * by the guest kernel. */
> kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr);
> @@ -416,32 +616,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct k=
vm_vcpu
> *vcpu,
> break;
> }
>=20
> - er =3D kvmppc_emulate_instruction(run, vcpu);
> - switch (er) {
> - case EMULATE_DONE:
> - /* don't overwrite subtypes, just account kvm_stats */
> - kvmppc_account_exit_stat(vcpu, EMULATED_INST_EXITS);
> - /* Future optimization: only reload non-volatiles if
> - * they were actually modified by emulation. */
> - r =3D RESUME_GUEST_NV;
> - break;
> - case EMULATE_DO_DCR:
> - run->exit_reason =3D KVM_EXIT_DCR;
> - r =3D RESUME_HOST;
> - break;
> - case EMULATE_FAIL:
> - /* XXX Deliver Program interrupt to guest. */
> - printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
> - __func__, vcpu->arch.pc, vcpu->arch.last_inst);
> - /* For debugging, encode the failing instruction and
> - * report it to userspace. */
> - run->hw.hardware_exit_reason =3D ~0ULL << 32;
> - run->hw.hardware_exit_reason |=3D vcpu->arch.last_inst;
> - r =3D RESUME_HOST;
> - break;
> - default:
> - BUG();
> - }
> + r =3D emulation_exit(run, vcpu);
> break;
>=20
> case BOOKE_INTERRUPT_FP_UNAVAIL:
> @@ -506,6 +681,21 @@ int kvmppc_handle_exit(struct kvm_run *run, struct k=
vm_vcpu
> *vcpu,
> r =3D RESUME_GUEST;
> break;
>=20
> +#ifdef CONFIG_KVM_BOOKE_HV
> + case BOOKE_INTERRUPT_HV_SYSCALL:
> + if (!(vcpu->arch.shared->msr & MSR_PR)) {
> + kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
> + } else {
> + /*
> + * hcall from guest userspace -- send privileged
> + * instruction program check.
> + */
> + kvmppc_core_queue_program(vcpu, ESR_PPR);
> + }
> +
> + r =3D RESUME_GUEST;
> + break;
> +#else
> case BOOKE_INTERRUPT_SYSCALL:
> if (!(vcpu->arch.shared->msr & MSR_PR) &&
> (((u32)kvmppc_get_gpr(vcpu, 0)) =3D=3D KVM_SC_MAGIC_R0)) {
> @@ -519,6 +709,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kv=
m_vcpu
> *vcpu,
> kvmppc_account_exit(vcpu, SYSCALL_EXITS);
> r =3D RESUME_GUEST;
> break;
> +#endif
>=20
> case BOOKE_INTERRUPT_DTLB_MISS: {
> unsigned long eaddr =3D vcpu->arch.fault_dear;
> @@ -659,12 +850,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
> int r;
>=20
> vcpu->arch.pc =3D 0;
> - vcpu->arch.shared->msr =3D 0;
> - vcpu->arch.shadow_msr =3D MSR_USER | MSR_DE | MSR_IS | MSR_DS;
> vcpu->arch.shared->pir =3D vcpu->vcpu_id;
> kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slo=
t
> */
> + kvmppc_set_msr(vcpu, 0);
>=20
> +#ifndef CONFIG_KVM_BOOKE_HV
> + vcpu->arch.shadow_msr =3D MSR_USER | MSR_DE | MSR_IS | MSR_DS;
> vcpu->arch.shadow_pid =3D 1;
> + vcpu->arch.shared->msr =3D 0;
> +#endif
>=20
> /* Eye-catching numbers so we know if the guest takes an interrupt
> * before it's programmed its own IVPR/IVORs. */
> @@ -745,8 +939,8 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
> sregs->u.e.csrr0 =3D vcpu->arch.csrr0;
> sregs->u.e.csrr1 =3D vcpu->arch.csrr1;
> sregs->u.e.mcsr =3D vcpu->arch.mcsr;
> - sregs->u.e.esr =3D vcpu->arch.shared->esr;
> - sregs->u.e.dear =3D vcpu->arch.shared->dar;
> + sregs->u.e.esr =3D get_guest_esr(vcpu);
> + sregs->u.e.dear =3D get_guest_dear(vcpu);
> sregs->u.e.tsr =3D vcpu->arch.tsr;
> sregs->u.e.tcr =3D vcpu->arch.tcr;
> sregs->u.e.dec =3D kvmppc_get_dec(vcpu, tb);
> @@ -763,8 +957,8 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
> vcpu->arch.csrr0 =3D sregs->u.e.csrr0;
> vcpu->arch.csrr1 =3D sregs->u.e.csrr1;
> vcpu->arch.mcsr =3D sregs->u.e.mcsr;
> - vcpu->arch.shared->esr =3D sregs->u.e.esr;
> - vcpu->arch.shared->dar =3D sregs->u.e.dear;
> + set_guest_esr(vcpu, sregs->u.e.esr);
> + set_guest_dear(vcpu, sregs->u.e.dear);
> vcpu->arch.vrsave =3D sregs->u.e.vrsave;
> kvmppc_set_tcr(vcpu, sregs->u.e.tcr);
>=20
> @@ -961,14 +1155,17 @@ void kvmppc_decrementer_func(unsigned long data)
>=20
> void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
> {
> + current->thread.kvm_vcpu =3D vcpu;
> }
>=20
> void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu)
> {
> + current->thread.kvm_vcpu =3D NULL;
> }
>=20
> int __init kvmppc_booke_init(void)
> {
> +#ifndef CONFIG_KVM_BOOKE_HV
> unsigned long ivor[16];
> unsigned long max_ivor =3D 0;
> int i;
> @@ -1011,7 +1208,7 @@ int __init kvmppc_booke_init(void)
> }
> flush_icache_range(kvmppc_booke_handlers,
> kvmppc_booke_handlers + max_ivor + kvmppc_handler_le=
n);
> -
> +#endif /* !BOOKE_HV */
> return 0;
> }
>=20
> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
> index 05d1d99..d53bcf2 100644
> --- a/arch/powerpc/kvm/booke.h
> +++ b/arch/powerpc/kvm/booke.h
> @@ -48,7 +48,20 @@
> #define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19
> /* Internal pseudo-irqprio for level triggered externals */
> #define BOOKE_IRQPRIO_EXTERNAL_LEVEL 20
> -#define BOOKE_IRQPRIO_MAX 20
> +#define BOOKE_IRQPRIO_DBELL 21
> +#define BOOKE_IRQPRIO_DBELL_CRIT 22
> +#define BOOKE_IRQPRIO_MAX 23
> +
> +#define BOOKE_IRQMASK_EE ((1 << BOOKE_IRQPRIO_EXTERNAL_LEVEL) | \
> + (1 << BOOKE_IRQPRIO_PERFORMANCE_MONITOR) | \
> + (1 << BOOKE_IRQPRIO_DBELL) | \
> + (1 << BOOKE_IRQPRIO_DECREMENTER) | \
> + (1 << BOOKE_IRQPRIO_FIT) | \
> + (1 << BOOKE_IRQPRIO_EXTERNAL))
> +
> +#define BOOKE_IRQMASK_CE ((1 << BOOKE_IRQPRIO_DBELL_CRIT) | \
> + (1 << BOOKE_IRQPRIO_WATCHDOG) | \
> + (1 << BOOKE_IRQPRIO_CRITICAL))
>=20
> extern unsigned long kvmppc_booke_handlers;
>=20
> @@ -74,4 +87,13 @@ void kvmppc_vcpu_disable_spe(struct kvm_vcpu *vcpu);
> void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
> void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu);
>=20
> +enum int_class {
> + INT_CLASS_NONCRIT,
> + INT_CLASS_CRIT,
> + INT_CLASS_MC,
> + INT_CLASS_DBG,
> +};
> +
> +void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class =
type);
> +
> #endif /* __KVM_BOOKE_H__ */
> diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_em=
ulate.c
> index 3e652da..904412b 100644
> --- a/arch/powerpc/kvm/booke_emulate.c
> +++ b/arch/powerpc/kvm/booke_emulate.c
> @@ -99,6 +99,12 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struc=
t
> kvm_vcpu *vcpu,
> return emulated;
> }
>=20
> +/*
> + * NOTE: some of these registers are not emulated on BOOKE_HV (GS-mode).
> + * Their backing store is in real registers, and these functions
> + * will return the wrong result if called for them in another context
> + * (such as debugging).
> + */
> int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
> {
> int emulated =3D EMULATE_DONE;
> @@ -122,9 +128,11 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu=
, int
> sprn, int rs)
> kvmppc_set_tcr(vcpu, spr_val);
> break;
>=20
> - /* Note: SPRG4-7 are user-readable. These values are
> - * loaded into the real SPRGs when resuming the
> - * guest. */
> + /*
> + * Note: SPRG4-7 are user-readable.
> + * These values are loaded into the real SPRGs when resuming the
> + * guest (PR-mode only).
> + */
> case SPRN_SPRG4:
> vcpu->arch.shared->sprg4 =3D spr_val; break;
> case SPRN_SPRG5:
> @@ -136,6 +144,9 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu,=
int
> sprn, int rs)
>=20
> case SPRN_IVPR:
> vcpu->arch.ivpr =3D spr_val;
> +#ifdef CONFIG_KVM_BOOKE_HV
> + mtspr(SPRN_GIVPR, spr_val);
> +#endif
> break;
> case SPRN_IVOR0:
> vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] =3D spr_val;
> @@ -145,6 +156,9 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu,=
int
> sprn, int rs)
> break;
> case SPRN_IVOR2:
> vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] =3D spr_val;
> +#ifdef CONFIG_KVM_BOOKE_HV
> + mtspr(SPRN_GIVOR2, spr_val);
> +#endif
> break;
> case SPRN_IVOR3:
> vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] =3D spr_val;
> @@ -163,6 +177,9 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu,=
int
> sprn, int rs)
> break;
> case SPRN_IVOR8:
> vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] =3D spr_val;
> +#ifdef CONFIG_KVM_BOOKE_HV
> + mtspr(SPRN_GIVOR8, spr_val);
> +#endif
> break;
> case SPRN_IVOR9:
> vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] =3D spr_val;
> diff --git a/arch/powerpc/kvm/bookehv_interrupts.S
> b/arch/powerpc/kvm/bookehv_interrupts.S
> new file mode 100644
> index 0000000..9eaeebd
> --- /dev/null
> +++ b/arch/powerpc/kvm/bookehv_interrupts.S
> @@ -0,0 +1,587 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, =
USA.
> + *
> + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
> + *
> + * Author: Varun Sethi <varun.sethi@freescale.com>
> + * Author: Scott Wood <scotwood@freescale.com>
> + *
> + * This file is derived from arch/powerpc/kvm/booke_interrupts.S
> + */
> +
> +#include <asm/ppc_asm.h>
> +#include <asm/kvm_asm.h>
> +#include <asm/reg.h>
> +#include <asm/mmu-44x.h>
> +#include <asm/page.h>
> +#include <asm/asm-compat.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/bitsperlong.h>
> +
> +#include "../kernel/head_booke.h" /* for THREAD_NORMSAVE() */
> +
> +#define GET_VCPU(vcpu, thread) \
> + PPC_LL vcpu, THREAD_KVM_VCPU(thread)
> +
> +#define SET_VCPU(vcpu) \
> + PPC_STL vcpu, (THREAD + THREAD_KVM_VCPU)(r2)
> +
> +#define LONGBYTES (BITS_PER_LONG / 8)
> +
> +#define VCPU_GPR(n) (VCPU_GPRS + (n * LONGBYTES))
> +#define VCPU_GUEST_SPRG(n) (VCPU_GUEST_SPRGS + (n * LONGBYTES))
> +
> +/* The host stack layout: */
> +#define HOST_R1 (0 * LONGBYTES) /* Implied by stwu. */
> +#define HOST_CALLEE_LR (1 * LONGBYTES)
> +#define HOST_RUN (2 * LONGBYTES) /* struct kvm_run */
> +/*
> + * r2 is special: it holds 'current', and it made nonvolatile in the
> + * kernel with the -ffixed-r2 gcc option.
> + */
> +#define HOST_R2 (3 * LONGBYTES)
> +#define HOST_NV_GPRS (4 * LONGBYTES)
> +#define HOST_NV_GPR(n) (HOST_NV_GPRS + ((n - 14) * LONGBYTES))
> +#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + LONGBYTES)
> +#define HOST_STACK_SIZE ((HOST_MIN_STACK_SIZE + 15) & ~15) /* Align. */
> +#define HOST_STACK_LR (HOST_STACK_SIZE + LONGBYTES) /* In caller stack=
frame.
> */
> +
> +#define NEED_EMU 0x00000001 /* emulation -- save nv regs */
> +#define NEED_DEAR 0x00000002 /* save faulting DEAR */
> +#define NEED_ESR 0x00000004 /* save faulting ESR */
> +
> +/*
> + * On entry:
> + * r4 =3D vcpu, r5 =3D srr0, r6 =3D srr1
> + * saved in vcpu: cr, ctr, r3-r13
> + */
> +.macro kvm_handler_common intno, srr0, flags
> + mfspr r10, SPRN_PID
> + lwz r8, VCPU_HOST_PID(r4)
> + PPC_LL r11, VCPU_SHARED(r4)
> + PPC_STL r14, VCPU_GPR(r14)(r4) /* We need a non-volatile GPR. */
> + li r14, \intno
> +
> + stw r10, VCPU_GUEST_PID(r4)
> + mtspr SPRN_PID, r8
> +
> + .if \flags & NEED_EMU
> + lwz r9, VCPU_KVM(r4)
> + .endif
> +
> +#ifdef CONFIG_KVM_EXIT_TIMING
> + /* save exit time */
> +1: mfspr r7, SPRN_TBRU
> + mfspr r8, SPRN_TBRL
> + mfspr r9, SPRN_TBRU
> + cmpw r9, r7
> + PPC_STL r8, VCPU_TIMING_EXIT_TBL(r4)
> + bne- 1b
> + PPC_STL r9, VCPU_TIMING_EXIT_TBU(r4)
> +#endif
> +
> + oris r8, r6, MSR_CE@h
> +#ifndef CONFIG_64BIT
> + stw r6, (VCPU_SHARED_MSR + 4)(r11)
> +#else
> + std r6, (VCPU_SHARED_MSR)(r11)
> +#endif
> + ori r8, r8, MSR_ME | MSR_RI
> + PPC_STL r5, VCPU_PC(r4)
> +
> + /*
> + * Make sure CE/ME/RI are set (if appropriate for exception type)
> + * whether or not the guest had it set. Since mfmsr/mtmsr are
> + * somewhat expensive, skip in the common case where the guest
> + * had all these bits set (and thus they're still set if
> + * appropriate for the exception type).
> + */
> + cmpw r6, r8
> + .if \flags & NEED_EMU
> + lwz r9, KVM_LPID(r9)
> + .endif
> + beq 1f
> + mfmsr r7
> + .if \srr0 !=3D SPRN_MCSRR0 && \srr0 !=3D SPRN_CSRR0
> + oris r7, r7, MSR_CE@h
> + .endif
> + .if \srr0 !=3D SPRN_MCSRR0
> + ori r7, r7, MSR_ME | MSR_RI
> + .endif
> + mtmsr r7
> +1:
> +
> + .if \flags & NEED_EMU
> + /*
> + * This assumes you have external PID support.
> + * To support a bookehv CPU without external PID, you'll
> + * need to look up the TLB entry and create a temporary mapping.
> + *
> + * FIXME: we don't currently handle if the lwepx faults. PR-mode
> + * booke doesn't handle it either. Since Linux doesn't use
> + * broadcast tlbivax anymore, the only way this should happen is
> + * if the guest maps its memory execute-but-not-read, or if we
> + * somehow take a TLB miss in the middle of this entry code and
> + * evict the relevant entry. On e500mc, all kernel lowmem is
> + * bolted into TLB1 large page mappings, and we don't use
> + * broadcast invalidates, so we should not take a TLB miss here.
> + *
> + * Later we'll need to deal with faults here. Disallowing guest
> + * mappings that are execute-but-not-read could be an option on
> + * e500mc, but not on chips with an LRAT if it is used.
> + */
> +
> + mfspr r3, SPRN_EPLC /* will already have correct ELPID and EGS */
> + PPC_STL r15, VCPU_GPR(r15)(r4)
> + PPC_STL r16, VCPU_GPR(r16)(r4)
> + PPC_STL r17, VCPU_GPR(r17)(r4)
> + PPC_STL r18, VCPU_GPR(r18)(r4)
> + PPC_STL r19, VCPU_GPR(r19)(r4)
> + mr r8, r3
> + PPC_STL r20, VCPU_GPR(r20)(r4)
> + rlwimi r8, r6, EPC_EAS_SHIFT - MSR_IR_LG, EPC_EAS
> + PPC_STL r21, VCPU_GPR(r21)(r4)
> + rlwimi r8, r6, EPC_EPR_SHIFT - MSR_PR_LG, EPC_EPR
> + PPC_STL r22, VCPU_GPR(r22)(r4)
> + rlwimi r8, r10, EPC_EPID_SHIFT, EPC_EPID
> + PPC_STL r23, VCPU_GPR(r23)(r4)
> + PPC_STL r24, VCPU_GPR(r24)(r4)
> + PPC_STL r25, VCPU_GPR(r25)(r4)
> + PPC_STL r26, VCPU_GPR(r26)(r4)
> + PPC_STL r27, VCPU_GPR(r27)(r4)
> + PPC_STL r28, VCPU_GPR(r28)(r4)
> + PPC_STL r29, VCPU_GPR(r29)(r4)
> + PPC_STL r30, VCPU_GPR(r30)(r4)
> + PPC_STL r31, VCPU_GPR(r31)(r4)
> + mtspr SPRN_EPLC, r8
> + isync
> + lwepx r9, 0, r5
> + mtspr SPRN_EPLC, r3
> + stw r9, VCPU_LAST_INST(r4)
> + .endif
> +
> + .if \flags & NEED_ESR
> + mfspr r8, SPRN_ESR
> + PPC_STL r8, VCPU_FAULT_ESR(r4)
> + .endif
> +
> + .if \flags & NEED_DEAR
> + mfspr r9, SPRN_DEAR
> + PPC_STL r9, VCPU_FAULT_DEAR(r4)
> + .endif
> +
> + b kvmppc_resume_host
> +.endm
> +
> +/*
> + * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_=
asm.h
> + */
> +.macro kvm_handler intno srr0, srr1, flags
> +_GLOBAL(kvmppc_handler_\intno\()_\srr1)
> + GET_VCPU(r11, r10)
> + PPC_STL r3, VCPU_GPR(r3)(r11)
> + mfspr r3, SPRN_SPRG_RSCRATCH0
> + PPC_STL r4, VCPU_GPR(r4)(r11)
> + PPC_LL r4, THREAD_NORMSAVE(0)(r10)
> + PPC_STL r5, VCPU_GPR(r5)(r11)
> + PPC_STL r13, VCPU_CR(r11)
> + mfspr r5, \srr0
> + PPC_STL r3, VCPU_GPR(r10)(r11)
> + PPC_LL r3, THREAD_NORMSAVE(2)(r10)
> + PPC_STL r6, VCPU_GPR(r6)(r11)
> + PPC_STL r4, VCPU_GPR(r11)(r11)
> + mfspr r6, \srr1
> + PPC_STL r7, VCPU_GPR(r7)(r11)
> + PPC_STL r8, VCPU_GPR(r8)(r11)
> + PPC_STL r9, VCPU_GPR(r9)(r11)
> + PPC_STL r3, VCPU_GPR(r13)(r11)
> + mfctr r7
> + PPC_STL r12, VCPU_GPR(r12)(r11)
> + PPC_STL r7, VCPU_CTR(r11)
> + mr r4, r11
> + kvm_handler_common \intno, \srr0, \flags
> +.endm
> +
> +.macro kvm_lvl_handler intno scratch srr0, srr1, flags
> +_GLOBAL(kvmppc_handler_\intno\()_\srr1)
> + mfspr r10, SPRN_SPRG_THREAD
> + GET_VCPU(r11, r10)
> + PPC_STL r3, VCPU_GPR(r3)(r11)
> + mfspr r3, \scratch
> + PPC_STL r4, VCPU_GPR(r4)(r11)
> + PPC_LL r4, GPR9(r8)
> + PPC_STL r5, VCPU_GPR(r5)(r11)
> + PPC_STL r9, VCPU_CR(r11)
> + mfspr r5, \srr0
> + PPC_STL r3, VCPU_GPR(r8)(r11)
> + PPC_LL r3, GPR10(r8)
> + PPC_STL r6, VCPU_GPR(r6)(r11)
> + PPC_STL r4, VCPU_GPR(r9)(r11)
> + mfspr r6, \srr1
> + PPC_LL r4, GPR11(r8)
> + PPC_STL r7, VCPU_GPR(r7)(r11)
> + PPC_STL r8, VCPU_GPR(r8)(r11)
> + PPC_STL r3, VCPU_GPR(r10)(r11)
> + mfctr r7
> + PPC_STL r12, VCPU_GPR(r12)(r11)
> + PPC_STL r4, VCPU_GPR(r11)(r11)
> + PPC_STL r7, VCPU_CTR(r11)
> + mr r4, r11
> + kvm_handler_common \intno, \srr0, \flags
> +.endm
> +
> +kvm_lvl_handler BOOKE_INTERRUPT_CRITICAL, \
> + SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
> +kvm_lvl_handler BOOKE_INTERRUPT_MACHINE_CHECK, \
> + SPRN_SPRG_RSCRATCH_MC, SPRN_MCSRR0, SPRN_MCSRR1, 0
> +kvm_handler BOOKE_INTERRUPT_DATA_STORAGE, \
> + SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR)
> +kvm_handler BOOKE_INTERRUPT_INST_STORAGE, SPRN_SRR0, SPRN_SRR1, NEED_ESR
> +kvm_handler BOOKE_INTERRUPT_EXTERNAL, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_ALIGNMENT, \
> + SPRN_SRR0, SPRN_SRR1, (NEED_DEAR | NEED_ESR)
> +kvm_handler BOOKE_INTERRUPT_PROGRAM, SPRN_SRR0, SPRN_SRR1, NEED_ESR
> +kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_SYSCALL, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_DECREMENTER, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_FIT, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_lvl_handler BOOKE_INTERRUPT_WATCHDOG, \
> + SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
> +kvm_handler BOOKE_INTERRUPT_DTLB_MISS, \
> + SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
> +kvm_handler BOOKE_INTERRUPT_ITLB_MISS, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_DOORBELL, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_lvl_handler BOOKE_INTERRUPT_DOORBELL_CRITICAL, \
> + SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
> +kvm_handler BOOKE_INTERRUPT_HV_PRIV, SPRN_SRR0, SPRN_SRR1, NEED_EMU
> +kvm_handler BOOKE_INTERRUPT_HV_SYSCALL, SPRN_SRR0, SPRN_SRR1, 0
> +kvm_handler BOOKE_INTERRUPT_GUEST_DBELL, SPRN_GSRR0, SPRN_GSRR1, 0
> +kvm_lvl_handler BOOKE_INTERRUPT_GUEST_DBELL_CRIT, \
> + SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
> +kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
> + SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
> +kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
> + SPRN_SPRG_RSCRATCH_DBG, SPRN_DSRR0, SPRN_DSRR1, 0
> +
> +
> +/* Registers:
> + * SPRG_SCRATCH0: guest r10
> + * r4: vcpu pointer
> + * r11: vcpu->arch.shared
> + * r14: KVM exit number
> + */
> +_GLOBAL(kvmppc_resume_host)
> + /* Save remaining volatile guest register state to vcpu. */
> + mfspr r3, SPRN_VRSAVE
> + PPC_STL r0, VCPU_GPR(r0)(r4)
> + PPC_STL r1, VCPU_GPR(r1)(r4)
> + mflr r5
> + mfspr r6, SPRN_SPRG4
> + PPC_STL r2, VCPU_GPR(r2)(r4)
> + PPC_STL r5, VCPU_LR(r4)
> + mfspr r7, SPRN_SPRG5
> + PPC_STL r3, VCPU_VRSAVE(r4)
> + PPC_STL r6, VCPU_SHARED_SPRG4(r11)
> + mfspr r8, SPRN_SPRG6
> + PPC_STL r7, VCPU_SHARED_SPRG5(r11)
> + mfspr r9, SPRN_SPRG7
> + PPC_STL r8, VCPU_SHARED_SPRG6(r11)
> + mfxer r3
> + PPC_STL r9, VCPU_SHARED_SPRG7(r11)
> +
> + /* save guest MAS registers and restore host mas4 & mas6 */
> + mfspr r5, SPRN_MAS0
> + PPC_STL r3, VCPU_XER(r4)
> + mfspr r6, SPRN_MAS1
> + stw r5, VCPU_SHARED_MAS0(r11)
> + mfspr r7, SPRN_MAS2
> + stw r6, VCPU_SHARED_MAS1(r11)
> +#ifndef CONFIG_64BIT
> + stw r7, (VCPU_SHARED_MAS2 + 4)(r11)
> +#else
> + std r7, (VCPU_SHARED_MAS2)(r11)
> +#endif
> + mfspr r5, SPRN_MAS3
> + mfspr r6, SPRN_MAS4
> + stw r5, VCPU_SHARED_MAS7_3+4(r11)
> + mfspr r7, SPRN_MAS6
> + stw r6, VCPU_SHARED_MAS4(r11)
> + mfspr r5, SPRN_MAS7
> + lwz r6, VCPU_HOST_MAS4(r4)
> + stw r7, VCPU_SHARED_MAS6(r11)
> + lwz r8, VCPU_HOST_MAS6(r4)
> + mtspr SPRN_MAS4, r6
> + stw r5, VCPU_SHARED_MAS7_3+0(r11)
> + mtspr SPRN_MAS6, r8
> + mfspr r3, SPRN_EPCR
> + rlwinm r3, r3, 0, ~SPRN_EPCR_DMIUH
> + mtspr SPRN_EPCR, r3
> + isync
> +
> + /* Restore host stack pointer */
> + PPC_LL r1, VCPU_HOST_STACK(r4)
> + PPC_LL r2, HOST_R2(r1)
> +
> + /* Switch to kernel stack and jump to handler. */
> + PPC_LL r3, HOST_RUN(r1)
> + mr r5, r14 /* intno */
> + mr r14, r4 /* Save vcpu pointer. */
> + bl kvmppc_handle_exit
> +
> + /* Restore vcpu pointer and the nonvolatiles we used. */
> + mr r4, r14
> + PPC_LL r14, VCPU_GPR(r14)(r4)
> +
> + andi. r5, r3, RESUME_FLAG_NV
> + beq skip_nv_load
> + PPC_LL r15, VCPU_GPR(r15)(r4)
> + PPC_LL r16, VCPU_GPR(r16)(r4)
> + PPC_LL r17, VCPU_GPR(r17)(r4)
> + PPC_LL r18, VCPU_GPR(r18)(r4)
> + PPC_LL r19, VCPU_GPR(r19)(r4)
> + PPC_LL r20, VCPU_GPR(r20)(r4)
> + PPC_LL r21, VCPU_GPR(r21)(r4)
> + PPC_LL r22, VCPU_GPR(r22)(r4)
> + PPC_LL r23, VCPU_GPR(r23)(r4)
> + PPC_LL r24, VCPU_GPR(r24)(r4)
> + PPC_LL r25, VCPU_GPR(r25)(r4)
> + PPC_LL r26, VCPU_GPR(r26)(r4)
> + PPC_LL r27, VCPU_GPR(r27)(r4)
> + PPC_LL r28, VCPU_GPR(r28)(r4)
> + PPC_LL r29, VCPU_GPR(r29)(r4)
> + PPC_LL r30, VCPU_GPR(r30)(r4)
> + PPC_LL r31, VCPU_GPR(r31)(r4)
> +skip_nv_load:
> + /* Should we return to the guest? */
> + andi. r5, r3, RESUME_FLAG_HOST
> + beq lightweight_exit
> +
> + srawi r3, r3, 2 /* Shift -ERR back down. */
> +
> +heavyweight_exit:
> + /* Not returning to guest. */
> + PPC_LL r5, HOST_STACK_LR(r1)
> +
> + /*
> + * We already saved guest volatile register state; now save the
> + * non-volatiles.
> + */
> +
> + PPC_STL r15, VCPU_GPR(r15)(r4)
> + PPC_STL r16, VCPU_GPR(r16)(r4)
> + PPC_STL r17, VCPU_GPR(r17)(r4)
> + PPC_STL r18, VCPU_GPR(r18)(r4)
> + PPC_STL r19, VCPU_GPR(r19)(r4)
> + PPC_STL r20, VCPU_GPR(r20)(r4)
> + PPC_STL r21, VCPU_GPR(r21)(r4)
> + PPC_STL r22, VCPU_GPR(r22)(r4)
> + PPC_STL r23, VCPU_GPR(r23)(r4)
> + PPC_STL r24, VCPU_GPR(r24)(r4)
> + PPC_STL r25, VCPU_GPR(r25)(r4)
> + PPC_STL r26, VCPU_GPR(r26)(r4)
> + PPC_STL r27, VCPU_GPR(r27)(r4)
> + PPC_STL r28, VCPU_GPR(r28)(r4)
> + PPC_STL r29, VCPU_GPR(r29)(r4)
> + PPC_STL r30, VCPU_GPR(r30)(r4)
> + PPC_STL r31, VCPU_GPR(r31)(r4)
> +
> + /* Load host non-volatile register state from host stack. */
> + PPC_LL r14, HOST_NV_GPR(r14)(r1)
> + PPC_LL r15, HOST_NV_GPR(r15)(r1)
> + PPC_LL r16, HOST_NV_GPR(r16)(r1)
> + PPC_LL r17, HOST_NV_GPR(r17)(r1)
> + PPC_LL r18, HOST_NV_GPR(r18)(r1)
> + PPC_LL r19, HOST_NV_GPR(r19)(r1)
> + PPC_LL r20, HOST_NV_GPR(r20)(r1)
> + PPC_LL r21, HOST_NV_GPR(r21)(r1)
> + PPC_LL r22, HOST_NV_GPR(r22)(r1)
> + PPC_LL r23, HOST_NV_GPR(r23)(r1)
> + PPC_LL r24, HOST_NV_GPR(r24)(r1)
> + PPC_LL r25, HOST_NV_GPR(r25)(r1)
> + PPC_LL r26, HOST_NV_GPR(r26)(r1)
> + PPC_LL r27, HOST_NV_GPR(r27)(r1)
> + PPC_LL r28, HOST_NV_GPR(r28)(r1)
> + PPC_LL r29, HOST_NV_GPR(r29)(r1)
> + PPC_LL r30, HOST_NV_GPR(r30)(r1)
> + PPC_LL r31, HOST_NV_GPR(r31)(r1)
> +
> + /* Return to kvm_vcpu_run(). */
> + mtlr r5
> + addi r1, r1, HOST_STACK_SIZE
> + /* r3 still contains the return code from kvmppc_handle_exit(). */
> + blr
> +
> +/* Registers:
> + * r3: kvm_run pointer
> + * r4: vcpu pointer
> + */
> +_GLOBAL(__kvmppc_vcpu_run)
> + stwu r1, -HOST_STACK_SIZE(r1)
> + PPC_STL r1, VCPU_HOST_STACK(r4) /* Save stack pointer to vcpu. */
> +
> + /* Save host state to stack. */
> + PPC_STL r3, HOST_RUN(r1)
> + mflr r3
> + PPC_STL r3, HOST_STACK_LR(r1)
> +
> + /* Save host non-volatile register state to stack. */
> + PPC_STL r14, HOST_NV_GPR(r14)(r1)
> + PPC_STL r15, HOST_NV_GPR(r15)(r1)
> + PPC_STL r16, HOST_NV_GPR(r16)(r1)
> + PPC_STL r17, HOST_NV_GPR(r17)(r1)
> + PPC_STL r18, HOST_NV_GPR(r18)(r1)
> + PPC_STL r19, HOST_NV_GPR(r19)(r1)
> + PPC_STL r20, HOST_NV_GPR(r20)(r1)
> + PPC_STL r21, HOST_NV_GPR(r21)(r1)
> + PPC_STL r22, HOST_NV_GPR(r22)(r1)
> + PPC_STL r23, HOST_NV_GPR(r23)(r1)
> + PPC_STL r24, HOST_NV_GPR(r24)(r1)
> + PPC_STL r25, HOST_NV_GPR(r25)(r1)
> + PPC_STL r26, HOST_NV_GPR(r26)(r1)
> + PPC_STL r27, HOST_NV_GPR(r27)(r1)
> + PPC_STL r28, HOST_NV_GPR(r28)(r1)
> + PPC_STL r29, HOST_NV_GPR(r29)(r1)
> + PPC_STL r30, HOST_NV_GPR(r30)(r1)
> + PPC_STL r31, HOST_NV_GPR(r31)(r1)
> +
> + /* Load guest non-volatiles. */
> + PPC_LL r14, VCPU_GPR(r14)(r4)
> + PPC_LL r15, VCPU_GPR(r15)(r4)
> + PPC_LL r16, VCPU_GPR(r16)(r4)
> + PPC_LL r17, VCPU_GPR(r17)(r4)
> + PPC_LL r18, VCPU_GPR(r18)(r4)
> + PPC_LL r19, VCPU_GPR(r19)(r4)
> + PPC_LL r20, VCPU_GPR(r20)(r4)
> + PPC_LL r21, VCPU_GPR(r21)(r4)
> + PPC_LL r22, VCPU_GPR(r22)(r4)
> + PPC_LL r23, VCPU_GPR(r23)(r4)
> + PPC_LL r24, VCPU_GPR(r24)(r4)
> + PPC_LL r25, VCPU_GPR(r25)(r4)
> + PPC_LL r26, VCPU_GPR(r26)(r4)
> + PPC_LL r27, VCPU_GPR(r27)(r4)
> + PPC_LL r28, VCPU_GPR(r28)(r4)
> + PPC_LL r29, VCPU_GPR(r29)(r4)
> + PPC_LL r30, VCPU_GPR(r30)(r4)
> + PPC_LL r31, VCPU_GPR(r31)(r4)
> +
> +
> +lightweight_exit:
> + PPC_STL r2, HOST_R2(r1)
> +
> + mfspr r3, SPRN_PID
> + stw r3, VCPU_HOST_PID(r4)
> + lwz r3, VCPU_GUEST_PID(r4)
> + mtspr SPRN_PID, r3
> +
> + /* Save vcpu pointer for the exception handlers
> + * must be done before loading guest r2.
> + */
> +// SET_VCPU(r4)
> +
> + PPC_LL r11, VCPU_SHARED(r4)
> + /* Save host mas4 and mas6 and load guest MAS registers */
> + mfspr r3, SPRN_MAS4
> + stw r3, VCPU_HOST_MAS4(r4)
> + mfspr r3, SPRN_MAS6
> + stw r3, VCPU_HOST_MAS6(r4)
> + lwz r3, VCPU_SHARED_MAS0(r11)
> + lwz r5, VCPU_SHARED_MAS1(r11)
> +#ifndef CONFIG_64BIT
> + lwz r6, (VCPU_SHARED_MAS2 + 4)(r11)
> +#else
> + ld r6, (VCPU_SHARED_MAS2)(r11)
> +#endif
> + lwz r7, VCPU_SHARED_MAS7_3+4(r11)
> + lwz r8, VCPU_SHARED_MAS4(r11)
> + mtspr SPRN_MAS0, r3
> + mtspr SPRN_MAS1, r5
> + mtspr SPRN_MAS2, r6
> + mtspr SPRN_MAS3, r7
> + mtspr SPRN_MAS4, r8
> + lwz r3, VCPU_SHARED_MAS6(r11)
> + lwz r5, VCPU_SHARED_MAS7_3+0(r11)
> + mtspr SPRN_MAS6, r3
> + mtspr SPRN_MAS7, r5
> + /* Disable MAS register updates via exception */
> + mfspr r3, SPRN_EPCR
> + oris r3, r3, SPRN_EPCR_DMIUH@h
> + mtspr SPRN_EPCR, r3
> +
> + /*
> + * Host interrupt handlers may have clobbered these guest-readable
> + * SPRGs, so we need to reload them here with the guest's values.
> + */
> + lwz r3, VCPU_VRSAVE(r4)
> + lwz r5, VCPU_SHARED_SPRG4(r11)
> + mtspr SPRN_VRSAVE, r3
> + lwz r6, VCPU_SHARED_SPRG5(r11)
> + mtspr SPRN_SPRG4W, r5
> + lwz r7, VCPU_SHARED_SPRG6(r11)
> + mtspr SPRN_SPRG5W, r6
> + lwz r8, VCPU_SHARED_SPRG7(r11)
> + mtspr SPRN_SPRG6W, r7
> + mtspr SPRN_SPRG7W, r8
> +
> + /* Load some guest volatiles. */
> + PPC_LL r3, VCPU_LR(r4)
> + PPC_LL r5, VCPU_XER(r4)
> + PPC_LL r6, VCPU_CTR(r4)
> + PPC_LL r7, VCPU_CR(r4)
> + PPC_LL r8, VCPU_PC(r4)
> +#ifndef CONFIG_64BIT
> + lwz r9, (VCPU_SHARED_MSR + 4)(r11)
> +#else
> + ld r9, (VCPU_SHARED_MSR)(r11)
> +#endif
> + PPC_LL r0, VCPU_GPR(r0)(r4)
> + PPC_LL r1, VCPU_GPR(r1)(r4)
> + PPC_LL r2, VCPU_GPR(r2)(r4)
> + PPC_LL r10, VCPU_GPR(r10)(r4)
> + PPC_LL r11, VCPU_GPR(r11)(r4)
> + PPC_LL r12, VCPU_GPR(r12)(r4)
> + PPC_LL r13, VCPU_GPR(r13)(r4)
> + mtlr r3
> + mtxer r5
> + mtctr r6
> + mtcr r7
> + mtsrr0 r8
> + mtsrr1 r9
> +
> +#ifdef CONFIG_KVM_EXIT_TIMING
> + /* save enter time */
> +1:
> + mfspr r6, SPRN_TBRU
> + mfspr r7, SPRN_TBRL
> + mfspr r8, SPRN_TBRU
> + cmpw r8, r6
Is not we should save guest CR after this otherwise this can corrupt it?
Thanks
-Bharat
> + PPC_STL r7, VCPU_TIMING_LAST_ENTER_TBL(r4)
> + bne 1b=09
> + PPC_STL r8, VCPU_TIMING_LAST_ENTER_TBU(r4)
> +#endif
> +
> + /* Finish loading guest volatiles and jump to guest. */
> + PPC_LL r5, VCPU_GPR(r5)(r4)
> + PPC_LL r6, VCPU_GPR(r6)(r4)
> + PPC_LL r7, VCPU_GPR(r7)(r4)
> + PPC_LL r8, VCPU_GPR(r8)(r4)=09
> + PPC_LL r9, VCPU_GPR(r9)(r4)
> +
> + PPC_LL r3, VCPU_GPR(r3)(r4)
> + PPC_LL r4, VCPU_GPR(r4)(r4)
> + rfi
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 9806ea5..a5c5ceb 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -109,6 +109,11 @@ int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
> goto out;
> #endif
>=20
> +#ifdef CONFIG_KVM_BOOKE_HV
> + if (!cpu_has_feature(CPU_FTR_EMB_HV))
> + goto out;
> +#endif
> +
> r =3D true;
>=20
> out:
> diff --git a/arch/powerpc/kvm/timing.h b/arch/powerpc/kvm/timing.h
> index 8167d42..bf191e7 100644
> --- a/arch/powerpc/kvm/timing.h
> +++ b/arch/powerpc/kvm/timing.h
> @@ -93,6 +93,12 @@ static inline void kvmppc_account_exit_stat(struct kvm=
_vcpu
> *vcpu, int type)
> case SIGNAL_EXITS:
> vcpu->stat.signal_exits++;
> break;
> + case DBELL_EXITS:
> + vcpu->stat.dbell_exits++;
> + break;
> + case GDBELL_EXITS:
> + vcpu->stat.gdbell_exits++;
> + break;
> }
> }
>=20
> --
> 1.6.0.2
>=20
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v3 1/2] powerpc/44x: Add new compatible value for EMAC node of APM821XX dts file.
From: Duc Dang @ 2012-03-05 10:57 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, David Miller, Josh Boyer,
Stefan Roese
Cc: netdev, Duc Dang, linuxppc-dev, linux-kernel
In-Reply-To: <1330920224-3006-1-git-send-email-dhdang@apm.com>
This compatible value will be used to distinguish some special features of APM821XX EMAC: no half duplex mode support, configuring jumbo frame.
Signed-off-by: Duc Dang <dhdang@apm.com>
---
v3:
No change since v1/v2 patch sets. Added for completeness.
arch/powerpc/boot/dts/bluestone.dts | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
index 2a56a0d..74876f7 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -222,7 +222,7 @@
EMAC0: ethernet@ef600c00 {
device_type = "network";
- compatible = "ibm,emac4sync";
+ compatible = "ibm,emac-apm821xx", "ibm,emac4sync";
interrupt-parent = <&EMAC0>;
interrupts = <0x0 0x1>;
#interrupt-cells = <1>;
--
1.7.5.4
^ permalink raw reply related
* [PATCH v3 2/2] powerpc/44x: Add more changes for APM821XX EMAC driver
From: Duc Dang @ 2012-03-05 10:58 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, David Miller, Josh Boyer,
Stefan Roese
Cc: netdev, Duc Dang, linuxppc-dev, linux-kernel
In-Reply-To: <1330920224-3006-1-git-send-email-dhdang@apm.com>
This patch includes:
Configure EMAC PHY clock source (clock from PHY or internal clock).
Do not advertise PHY half duplex capability as APM821XX EMAC does not support half duplex mode.
Add changes to support configuring jumbo frame for APM821XX EMAC.
Signed-off-by: Duc Dang <dhdang@apm.com>
---
v3:
Add parentheses for multi-line statements.
Drop #if defined(CONFIG_APM821xx) in emac.h.
drivers/net/ethernet/ibm/emac/core.c | 29 ++++++++++++++++++++++++++++-
drivers/net/ethernet/ibm/emac/core.h | 13 +++++++++++--
drivers/net/ethernet/ibm/emac/emac.h | 2 ++
3 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 2abce96..cc51842 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -434,6 +434,11 @@ static inline u32 emac_iff2rmr(struct net_device *ndev)
else if (!netdev_mc_empty(ndev))
r |= EMAC_RMR_MAE;
+ if (emac_has_feature(dev, EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE)) {
+ r &= ~EMAC4_RMR_MJS_MASK;
+ r |= EMAC4_RMR_MJS(ndev->mtu);
+ }
+
return r;
}
@@ -965,6 +970,7 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)
int rx_sync_size = emac_rx_sync_size(new_mtu);
int rx_skb_size = emac_rx_skb_size(new_mtu);
int i, ret = 0;
+ int mr1_jumbo_bit_change = 0;
mutex_lock(&dev->link_lock);
emac_netif_stop(dev);
@@ -1013,7 +1019,15 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)
}
skip:
/* Check if we need to change "Jumbo" bit in MR1 */
- if ((new_mtu > ETH_DATA_LEN) ^ (dev->ndev->mtu > ETH_DATA_LEN)) {
+ if (emac_has_feature(dev, EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE)) {
+ mr1_jumbo_bit_change = (new_mtu > ETH_DATA_LEN) ||
+ (dev->ndev->mtu > ETH_DATA_LEN);
+ } else {
+ mr1_jumbo_bit_change = (new_mtu > ETH_DATA_LEN) ^
+ (dev->ndev->mtu > ETH_DATA_LEN);
+ }
+
+ if (mr1_jumbo_bit_change) {
/* This is to prevent starting RX channel in emac_rx_enable() */
set_bit(MAL_COMMAC_RX_STOPPED, &dev->commac.flags);
@@ -2471,6 +2485,7 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
/* Disable any PHY features not supported by the platform */
dev->phy.def->features &= ~dev->phy_feat_exc;
+ dev->phy.features &= ~dev->phy_feat_exc;
/* Setup initial link parameters */
if (dev->phy.features & SUPPORTED_Autoneg) {
@@ -2568,6 +2583,11 @@ static int __devinit emac_init_config(struct emac_instance *dev)
if (of_device_is_compatible(np, "ibm,emac-405ex") ||
of_device_is_compatible(np, "ibm,emac-405exr"))
dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
+ if (of_device_is_compatible(np, "ibm,emac-apm821xx")) {
+ dev->features |= (EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE |
+ EMAC_FTR_APM821XX_NO_HALF_DUPLEX |
+ EMAC_FTR_460EX_PHY_CLK_FIX);
+ }
} else if (of_device_is_compatible(np, "ibm,emac4")) {
dev->features |= EMAC_FTR_EMAC4;
if (of_device_is_compatible(np, "ibm,emac-440gx"))
@@ -2818,6 +2838,13 @@ static int __devinit emac_probe(struct platform_device *ofdev)
dev->stop_timeout = STOP_TIMEOUT_100;
INIT_DELAYED_WORK(&dev->link_work, emac_link_timer);
+ /* Some SoCs like APM821xx does not support Half Duplex mode. */
+ if (emac_has_feature(dev, EMAC_FTR_APM821XX_NO_HALF_DUPLEX)) {
+ dev->phy_feat_exc = (SUPPORTED_1000baseT_Half |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_10baseT_Half);
+ }
+
/* Find PHY if any */
err = emac_init_phy(dev);
if (err != 0)
diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index fa3ec57..9dea85a 100644
--- a/drivers/net/ethernet/ibm/emac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -325,7 +325,14 @@ struct emac_instance {
* Set if we need phy clock workaround for 460ex or 460gt
*/
#define EMAC_FTR_460EX_PHY_CLK_FIX 0x00000400
-
+/*
+ * APM821xx requires Jumbo frame size set explicitly
+ */
+#define EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE 0x00000800
+/*
+ * APM821xx does not support Half Duplex mode
+ */
+#define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000
/* Right now, we don't quite handle the always/possible masks on the
* most optimal way as we don't have a way to say something like
@@ -353,7 +360,9 @@ enum {
EMAC_FTR_NO_FLOW_CONTROL_40x |
#endif
EMAC_FTR_460EX_PHY_CLK_FIX |
- EMAC_FTR_440EP_PHY_CLK_FIX,
+ EMAC_FTR_440EP_PHY_CLK_FIX |
+ EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE |
+ EMAC_FTR_APM821XX_NO_HALF_DUPLEX,
};
static inline int emac_has_feature(struct emac_instance *dev,
diff --git a/drivers/net/ethernet/ibm/emac/emac.h b/drivers/net/ethernet/ibm/emac/emac.h
index 1568278..c9090a4 100644
--- a/drivers/net/ethernet/ibm/emac/emac.h
+++ b/drivers/net/ethernet/ibm/emac/emac.h
@@ -212,6 +212,8 @@ struct emac_regs {
#define EMAC4_RMR_RFAF_64_1024 0x00000006
#define EMAC4_RMR_RFAF_128_2048 0x00000007
#define EMAC4_RMR_BASE EMAC4_RMR_RFAF_128_2048
+#define EMAC4_RMR_MJS_MASK 0x0001fff8
+#define EMAC4_RMR_MJS(s) (((s) << 3) & EMAC4_RMR_MJS_MASK)
/* EMACx_ISR & EMACx_ISER */
#define EMAC4_ISR_TXPE 0x20000000
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH 13/38] KVM: PPC: booke: category E.HV (GS-mode) support
From: tiejun.chen @ 2012-03-05 9:57 UTC (permalink / raw)
To: Bhushan Bharat-R65777
Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org, Alexander Graf,
kvm-ppc@vger.kernel.org, kvm@vger.kernel.org
In-Reply-To: <6A3DF150A5B70D4F9B66A25E3F7C888D154397@039-SN2MPN1-023.039d.mgd.msft.net>
>> + /*
>> + * Host interrupt handlers may have clobbered these guest-readable
>> + * SPRGs, so we need to reload them here with the guest's values.
>> + */
>> + lwz r3, VCPU_VRSAVE(r4)
>> + lwz r5, VCPU_SHARED_SPRG4(r11)
>> + mtspr SPRN_VRSAVE, r3
>> + lwz r6, VCPU_SHARED_SPRG5(r11)
>> + mtspr SPRN_SPRG4W, r5
>> + lwz r7, VCPU_SHARED_SPRG6(r11)
>> + mtspr SPRN_SPRG5W, r6
>> + lwz r8, VCPU_SHARED_SPRG7(r11)
>> + mtspr SPRN_SPRG6W, r7
>> + mtspr SPRN_SPRG7W, r8
>> +
That should be here.
>> + /* Load some guest volatiles. */
>> + PPC_LL r3, VCPU_LR(r4)
>> + PPC_LL r5, VCPU_XER(r4)
>> + PPC_LL r6, VCPU_CTR(r4)
>> + PPC_LL r7, VCPU_CR(r4)
>> + PPC_LL r8, VCPU_PC(r4)
>> +#ifndef CONFIG_64BIT
>> + lwz r9, (VCPU_SHARED_MSR + 4)(r11)
>> +#else
>> + ld r9, (VCPU_SHARED_MSR)(r11)
>> +#endif
>> + PPC_LL r0, VCPU_GPR(r0)(r4)
>> + PPC_LL r1, VCPU_GPR(r1)(r4)
>> + PPC_LL r2, VCPU_GPR(r2)(r4)
>> + PPC_LL r10, VCPU_GPR(r10)(r4)
>> + PPC_LL r11, VCPU_GPR(r11)(r4)
>> + PPC_LL r12, VCPU_GPR(r12)(r4)
>> + PPC_LL r13, VCPU_GPR(r13)(r4)
>> + mtlr r3
>> + mtxer r5
>> + mtctr r6
>> + mtcr r7
>> + mtsrr0 r8
>> + mtsrr1 r9
>> +
>> +#ifdef CONFIG_KVM_EXIT_TIMING
>> + /* save enter time */
>> +1:
>> + mfspr r6, SPRN_TBRU
>> + mfspr r7, SPRN_TBRL
>> + mfspr r8, SPRN_TBRU
>> + cmpw r8, r6
>
> Is not we should save guest CR after this otherwise this can corrupt it?
I think this should be a typo since in our previous kvm implementation, we
always did collect kvm exit timing at the above location :)
Tiejun
>
> Thanks
> -Bharat
>
>> + PPC_STL r7, VCPU_TIMING_LAST_ENTER_TBL(r4)
>> + bne 1b
>> + PPC_STL r8, VCPU_TIMING_LAST_ENTER_TBU(r4)
>> +#endif
>> +
>> + /* Finish loading guest volatiles and jump to guest. */
>> + PPC_LL r5, VCPU_GPR(r5)(r4)
>> + PPC_LL r6, VCPU_GPR(r6)(r4)
>> + PPC_LL r7, VCPU_GPR(r7)(r4)
>> + PPC_LL r8, VCPU_GPR(r8)(r4)
>> + PPC_LL r9, VCPU_GPR(r9)(r4)
>> +
>> + PPC_LL r3, VCPU_GPR(r3)(r4)
>> + PPC_LL r4, VCPU_GPR(r4)(r4)
>> + rfi
^ permalink raw reply
* Re: [PATCH] powerpc/srio: Fix the compile errors when building with 64bit
From: Liu Gang @ 2012-03-05 14:20 UTC (permalink / raw)
To: Kumar Gala
Cc: r58472, Paul Gortmaker, linux-kernel, r61911, Alexandre.Bounine,
akpm, linuxppc-dev, Shaohui Xie
In-Reply-To: <6BFCD6C7-7675-4A99-9C4C-4E86FA5642A4@kernel.crashing.org>
Hi, Kumar,
On Fri, 2012-03-02 at 09:11 -0600, Kumar Gala wrote:
> > diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
> > index 1548578..468011e 100644
> > --- a/arch/powerpc/sysdev/fsl_rmu.c
> > +++ b/arch/powerpc/sysdev/fsl_rmu.c
> > @@ -311,8 +311,8 @@ fsl_rio_dbell_handler(int irq, void *dev_instance)
> >
> > /* XXX Need to check/dispatch until queue empty */
> > if (dsr & DOORBELL_DSR_DIQI) {
> > - u32 dmsg =
> > - (u32) fsl_dbell->dbell_ring.virt +
> > + unsigned long dmsg =
> > + (unsigned long) fsl_dbell->dbell_ring.virt +
> > (in_be32(&fsl_dbell->dbell_regs->dqdpar) & 0xfff);
> > struct rio_dbell *dbell;
> > int found = 0;
> > @@ -657,7 +657,8 @@ fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
> > int ret = 0;
> >
> > pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \
> > - "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len);
> > + "%8.8lx len %8.8zx\n", rdev->destid, mbox,
> > + (unsigned long)buffer, len);
> > if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
> > ret = -EINVAL;
> > goto out;
>
> For this case it seems as if some cast should be added to DBELL_* macros
Do you mean the DBELL_* macro should be added the cast "u16" and like
this:
#define DBELL_SID(x) (u16)(*(u16 *)(x + DOORBELL_SID_OFFSET))
> > @@ -972,7 +973,7 @@ out:
> > void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
> > {
> > struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
> > - u32 phys_buf, virt_buf;
> > + unsigned long phys_buf, virt_buf;
>
> Do you really want to change phys_buf to an 'unsigned long'?
>
> Should virt_buf really be void * here?
I think you are right, the phys_buf should not be changed to 'unsigned
long' and the virt_buf should be void *. I'll correct this in next
version.
> > @@ -982,7 +983,7 @@ void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
>
> The memcpy later could remove a cast if you make virt_buf a void *.
Thanks a lot, will remove.
Best Regards,
Liu Gang
^ permalink raw reply
* Intermittent failures enumerating PCIe devices on P2020
From: Matias Garcia @ 2012-03-05 15:13 UTC (permalink / raw)
To: linuxppc-dev
I'm getting intermittent failures enumerating four PCIe endpoints and
looking for some help. Sometimes three will enumerate, sometimes
fewer, sometimes four but only three of them will have BARs mapped,
etc.
I'm running 2.6.37 on a Freescale P2020 (e500v2 cores), and I have
four PCIe end-points (FPGAs) routed to one of the PCIe controllers
through a PCIe switch in a 1x2->4x1 configuration. On hard boot, the
FPGAs are configured via flash PROMs sometime after U-Boot does a PCI
scan and long before the kernel is booted. On soft boot, they remain
programmed.
I've tried simply rebooting, and this yields intermittent behaviour.
I've also tried suppressing the PCIe cores until after boot, flipping
a bit in the controller (which shuts it off if there are no
end-points) and rescanning the bus. This also produces intermittent
results. I'm attaching the output of lspci -v in the success case
where all four are enumerated, and the dtc where PCI is concerned. I'd
appreciate comments on the dtc as I'm just a hack on that front.
Let me know if other data is pertinent.
Cheers,
Matias Garcia
dtc:
/*
* There are three PCIe controllers defined here. The second is unconnected.
* Prefetchable memory was removed since our writes and reads are always
* order-dependant. Each PCIe controller has its own 32-bit memory space,
* and I/O is in yet another, for clarity.
* The vidproc controller is still in the top half of the 0x8 space for
* historical reasons (and symmetry...)
*
* Global PCIe memory map:
* PCIe1 Memory 0x880000000-0x88fffffff 256 MB
* PCIe2 Memory 0x990000000-0x99fffffff 256 MB
* PCIe3 Memory 0xaa0000000-0xaafffffff 256 MB
* I/O space 0xcc0000000-0xcc002ffff 64 KB * 3
*
* WARNING: The I/O memory is remapped and *@^#&$ by the kernel. Do not use.
*
* The third PCIe controller could be given an extra 256MB (or 1 GB
total, possibly)
* by reserving extra memory in the LAW BARs (law.c) and TLBs (tlb.c)
*/
/* Vidproc PCIe controller */
pci0: pcie@8ff70a000 {
cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0x8 0xff70a000 0x0 0x00001000>;
bus-range = <0 255>; /* primary / subordinate */
/*
* Memory 0x880000000-0x88fffffff 256 MB
* I/O 0xcc0000000-0xcc000ffff 64 KB
*/
ranges = <
0x02000000 /* flags = IORESOURCE_MEM */
0x0 0x80000000 /* start */
0x8 0x80000000 /* parent-phys */
0x0 0x10000000 /* size = 256 MB */
0x01000000 /* flags = IORESOURCE_IO */
0x0 0x00000000 /* start */
0xc 0xc0000000 /* parent-phys */
0x0 0x00010000 /* size = 64 KB */
>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <26 2>; /* Internal interrupt 10 */
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
/*
* The second cell of an interrupt is the sense.
*
* Kernel Sense DTS
* 1 Edge Rising 0
* 8 Level Low 1
* 4 Level High 2
* 2 Edge Falling 3
*/
interrupt-map = <
// IDSEL 0x0
0000 0x0 0x0 0x1 &mpic 0x0 0x0
0000 0x0 0x0 0x2 &mpic 0x1 0x0
0000 0x0 0x0 0x3 &mpic 0x4 0x0
0000 0x0 0x0 0x4 &mpic 0x4 0x0
>;
pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <
0x02000000 /* flags = IORESOURCE_MEM */
0x0 0x80000000 /* start */
0x02000000
0x0 0x80000000
0x0 0x10000000 /* size = 256 MB */
0x01000000 /* flags = IORESOURCE_IO */
0x0 0x0 /* start */
0x01000000 0x0 0x0
0x0 0x00010000>; /* size = 64 KB */
};
};
/* Not connected */
pci1: pcie@8ff709000 {
cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0x8 0xff709000 0x0 0x00001000>;
status = "disabled";
bus-range = <0 255>; /* primary / subordinate */
/*
* Memory 0x990000000-0x99fffffff 256 MB
* I/O 0xcc0010000-0xcc001ffff 64 KB
*/
ranges = <
0x02000000 /* flags = IORESOURCE_MEM */
0x0 0x90000000 /* start */
0x9 0x90000000 /* parent-phys */
0x0 0x10000000 /* size = 256 MB */
0x01000000 /* flags = IORESOURCE_IO */
0x0 0x00000000 /* start */
0xc 0xc0010000 /* parent-phys */
0x0 0x00010000 /* size = 64 KB */
>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <26 2>; /* Internal interrupt 10 */
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
/*
* The second cell of an interrupt is the sense.
*
* Kernel Sense DTS
* 1 Edge Rising 0
* 8 Level Low 1
* 4 Level High 2
* 2 Edge Falling 3
*/
interrupt-map = <
// IDSEL 0x0
0000 0x0 0x0 0x1 &mpic 0x0 0x0
0000 0x0 0x0 0x2 &mpic 0x1 0x0
0000 0x0 0x0 0x3 &mpic 0x4 0x0
0000 0x0 0x0 0x4 &mpic 0x4 0x0
>;
pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <
0x02000000 /* flags = IORESOURCE_MEM */
0x0 0x90000000 /* start */
0x02000000
0x0 0x90000000
0x0 0x10000000 /* size = 256 MB */
0x01000000 /* flags = IORESOURCE_IO */
0x0 0x0 /* start */
0x01000000
0x0 0x0
0x0 0x00010000>; /* size = 64 KB */
};
};
/* MMIB PCIe controller (x2 to PCIe switch) */
pci2: pcie@8ff708000 {
cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0x8 0xff708000 0x0 0x00001000>;
bus-range = <0 255>; /* primary / subordinate */
/*
* Memory 0xaa0000000-0xaafffffff 256 MB
* I/O 0xcc0020000-0xcc002ffff 64 KB
*/
ranges = <
0x02000000 /* flags = IORESOURCE_MEM */
0x0 0xa0000000 /* start */
0xa 0xa0000000 /* parent-phys */
0x0 0x10000000 /* size = 512 MB */
0x01000000 /* flags = IORESOURCE_IO */
0x0 0x00000000 /* start */
0xc 0xc0020000 /* parent-phys */
0x0 0x00010000 /* size = 64 KB */
>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <26 2>; /* Internal interrupt 10 */
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
/*
* The second cell of an interrupt is the sense.
*
* Kernel Sense DTS
* 1 Edge Rising 0
* 8 Level Low 1
* 4 Level High 2
* 2 Edge Falling 3
*/
interrupt-map = <
// IDSEL 0x0
0000 0x0 0x0 0x1 &mpic 0x0 0x0
0000 0x0 0x0 0x2 &mpic 0x1 0x0
0000 0x0 0x0 0x3 &mpic 0x4 0x0
0000 0x0 0x0 0x4 &mpic 0x4 0x0
>;
pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <
0x02000000 /* flags = IORESOURCE_MEM */
0x0 0xa0000000 /* start */
0x02000000
0x0 0xa0000000
0x0 0x10000000 /* size = 256 MB */
0x01000000 /* flags = IORESOURCE_IO */
0x0 0x0 /* start */
0x01000000 0x0 0x0
0x0 0x00010000>; /* size = 64 KB */
};
};
};
LSPCI -v:
0000:00:00.0 PCI bridge: Freescale Semiconductor Inc P2020 (rev 21)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Memory at <ignored> (32-bit, non-prefetchable)
Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
I/O behind bridge: 00000000-00000fff
Memory behind bridge: 80000000-8fffffff
Capabilities: [44] Power Management version 2
Capabilities: [4c] Express Root Port (Slot-), MSI 00
Capabilities: [100] Advanced Error Reporting
0000:01:00.0 Network and computing encryption device: Altera
Corporation Device 0004 (rev 01)
Subsystem: Altera Corporation Device 0004
Flags: fast devsel, IRQ 23
Memory at 880000000 (32-bit, non-prefetchable) [size=16M]
Memory at 881000000 (32-bit, non-prefetchable) [size=16M]
Memory at 882000000 (32-bit, non-prefetchable) [size=16M]
Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [100] Virtual Channel
Kernel driver in use: altera
Kernel modules: amazon_drivers
0001:02:00.0 PCI bridge: Freescale Semiconductor Inc P2020 (rev 21)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Memory at <ignored> (32-bit, non-prefetchable)
Bus: primary=00, secondary=03, subordinate=03, sec-latency=0
I/O behind bridge: 00000000-00000fff
Memory behind bridge: 90000000-9fffffff
Capabilities: [44] Power Management version 2
Capabilities: [4c] Express Root Port (Slot-), MSI 00
Capabilities: [100] Advanced Error Reporting
0002:04:00.0 PCI bridge: Freescale Semiconductor Inc P2020 (rev 21)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Memory at <ignored> (32-bit, non-prefetchable)
Bus: primary=00, secondary=05, subordinate=0a, sec-latency=0
I/O behind bridge: 00000000-00000fff
Memory behind bridge: a0000000-afffffff
Capabilities: [44] Power Management version 2
Capabilities: [4c] Express Root Port (Slot-), MSI 00
Capabilities: [100] Advanced Error Reporting
0002:05:00.0 PCI bridge: PLX Technology, Inc. Device 8606 (rev ba)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Memory at aa8000000 (32-bit, non-prefetchable) [size=128K]
Bus: primary=05, secondary=06, subordinate=0a, sec-latency=0
Memory behind bridge: a0000000-a7ffffff
Capabilities: [40] Power Management version 3
Capabilities: [48] MSI: Enable+ Count=1/4 Maskable+ 64bit+
Capabilities: [68] Express Upstream Port, MSI 00
Capabilities: [a4] Subsystem: PLX Technology, Inc. Device 8606
Capabilities: [100] Device Serial Number ba-86-01-10-b5-df-0e-00
Capabilities: [fb4] Advanced Error Reporting
Capabilities: [138] Power Budgeting <?>
Capabilities: [148] Virtual Channel
Capabilities: [448] Vendor Specific Information: ID=0000 Rev=0
Len=0cc <?>
Capabilities: [950] Vendor Specific Information: ID=0001 Rev=0
Len=010 <?>
Kernel driver in use: pcieport
0002:06:01.0 PCI bridge: PLX Technology, Inc. Device 8606 (rev ba)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Bus: primary=06, secondary=07, subordinate=07, sec-latency=0
Memory behind bridge: a0000000-a1ffffff
Capabilities: [40] Power Management version 3
Capabilities: [48] MSI: Enable+ Count=1/4 Maskable+ 64bit+
Capabilities: [68] Express Downstream Port (Slot+), MSI 00
Capabilities: [a4] Subsystem: PLX Technology, Inc. Device 8606
Capabilities: [100] Device Serial Number ba-86-01-10-b5-df-0e-00
Capabilities: [fb4] Advanced Error Reporting
Capabilities: [148] Virtual Channel
Capabilities: [520] Access Control Services
Capabilities: [950] Vendor Specific Information: ID=0001 Rev=0
Len=010 <?>
Kernel driver in use: pcieport
0002:06:05.0 PCI bridge: PLX Technology, Inc. Device 8606 (rev ba)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Bus: primary=06, secondary=08, subordinate=08, sec-latency=0
Memory behind bridge: a2000000-a3ffffff
Capabilities: [40] Power Management version 3
Capabilities: [48] MSI: Enable+ Count=1/4 Maskable+ 64bit+
Capabilities: [68] Express Downstream Port (Slot+), MSI 00
Capabilities: [a4] Subsystem: PLX Technology, Inc. Device 8606
Capabilities: [100] Device Serial Number ba-86-01-10-b5-df-0e-00
Capabilities: [fb4] Advanced Error Reporting
Capabilities: [148] Virtual Channel
Capabilities: [520] Access Control Services
Capabilities: [950] Vendor Specific Information: ID=0001 Rev=0
Len=010 <?>
Kernel driver in use: pcieport
0002:06:07.0 PCI bridge: PLX Technology, Inc. Device 8606 (rev ba)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Bus: primary=06, secondary=09, subordinate=09, sec-latency=0
Memory behind bridge: a4000000-a5ffffff
Capabilities: [40] Power Management version 3
Capabilities: [48] MSI: Enable+ Count=1/4 Maskable+ 64bit+
Capabilities: [68] Express Downstream Port (Slot+), MSI 00
Capabilities: [a4] Subsystem: PLX Technology, Inc. Device 8606
Capabilities: [100] Device Serial Number ba-86-01-10-b5-df-0e-00
Capabilities: [fb4] Advanced Error Reporting
Capabilities: [148] Virtual Channel
Capabilities: [520] Access Control Services
Capabilities: [950] Vendor Specific Information: ID=0001 Rev=0
Len=010 <?>
Kernel driver in use: pcieport
0002:06:09.0 PCI bridge: PLX Technology, Inc. Device 8606 (rev ba)
(prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0
Bus: primary=06, secondary=0a, subordinate=0a, sec-latency=0
Memory behind bridge: a6000000-a7ffffff
Capabilities: [40] Power Management version 3
Capabilities: [48] MSI: Enable+ Count=1/4 Maskable+ 64bit+
Capabilities: [68] Express Downstream Port (Slot+), MSI 00
Capabilities: [a4] Subsystem: PLX Technology, Inc. Device 8606
Capabilities: [100] Device Serial Number ba-86-01-10-b5-df-0e-00
Capabilities: [fb4] Advanced Error Reporting
Capabilities: [148] Virtual Channel
Capabilities: [520] Access Control Services
Capabilities: [950] Vendor Specific Information: ID=0001 Rev=0
Len=010 <?>
Kernel driver in use: pcieport
0002:07:00.0 Network and computing encryption device: Altera
Corporation Device 0004 (rev 01)
Subsystem: Altera Corporation Device 0004
Flags: fast devsel, IRQ 24
Memory at aa0000000 (32-bit, non-prefetchable) [size=16M]
Memory at aa1000000 (32-bit, non-prefetchable) [size=16M]
Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [100] Virtual Channel
Kernel driver in use: altera
Kernel modules: amazon_drivers
0002:08:00.0 Network and computing encryption device: Altera
Corporation Device 0004 (rev 01)
Subsystem: Altera Corporation Device 0004
Flags: fast devsel, IRQ 24
Memory at aa2000000 (32-bit, non-prefetchable) [size=16M]
Memory at aa3000000 (32-bit, non-prefetchable) [size=16M]
Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [100] Virtual Channel
Kernel driver in use: altera
Kernel modules: amazon_drivers
0002:09:00.0 Network and computing encryption device: Altera
Corporation Device 0004 (rev 01)
Subsystem: Altera Corporation Device 0004
Flags: fast devsel, IRQ 25
Memory at aa4000000 (32-bit, non-prefetchable) [size=16M]
Memory at aa5000000 (32-bit, non-prefetchable) [size=16M]
Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [100] Virtual Channel
Kernel driver in use: altera
Kernel modules: amazon_drivers
0002:0a:00.0 Network and computing encryption device: Altera
Corporation Device 0004 (rev 01)
Subsystem: Altera Corporation Device 0004
Flags: fast devsel, IRQ 24
Memory at aa6000000 (32-bit, non-prefetchable) [size=16M]
Memory at aa7000000 (32-bit, non-prefetchable) [size=16M]
Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [100] Virtual Channel
Kernel driver in use: altera
Kernel modules: amazon_drivers
^ permalink raw reply
* Re: linux-next: boot failure for next-20120227 and later (pci tree related)
From: Bjorn Helgaas @ 2012-03-05 16:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Stephen Rothwell, linux-next, ppc-dev, linux-kernel, Jesse Barnes
In-Reply-To: <1330918440.11728.87.camel@pasglop>
On Sun, Mar 4, 2012 at 8:34 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Sat, 2012-03-03 at 08:52 +1100, Benjamin Herrenschmidt wrote:
>
>> Or give me a chance to dig :-) I'll have a look next week.
>
> This is indeed what bjorn suspected on irc, this patch fixes it:
>
> (Bjorn, please fold it in the original offending patch)
Thanks for checking this out. Sparc should have the same problem, so
I'll post both updates in a bit.
Bjorn
> diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_=
of_scan.c
> index b37d0b5..5dd63f1 100644
> --- a/arch/powerpc/kernel/pci_of_scan.c
> +++ b/arch/powerpc/kernel/pci_of_scan.c
> @@ -75,6 +75,7 @@ static void of_pci_parse_addrs(struct device_node *node=
, struct pci_dev *dev)
> =A0{
> =A0 =A0 =A0 =A0u64 base, size;
> =A0 =A0 =A0 =A0unsigned int flags;
> + =A0 =A0 =A0 struct pci_bus_region region;
> =A0 =A0 =A0 =A0struct resource *res;
> =A0 =A0 =A0 =A0const u32 *addrs;
> =A0 =A0 =A0 =A0u32 i;
> @@ -106,10 +107,12 @@ static void of_pci_parse_addrs(struct device_node *=
node, struct pci_dev *dev)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_ERR "PCI: bad =
cfg reg num 0x%x\n", i);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 res->start =3D base;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 res->end =3D base + size - 1;
> +
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0res->flags =3D flags;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0res->name =3D pci_name(dev);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 region.start =3D base;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 region.end =3D base + size - 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pcibios_bus_to_resource(dev, res, ®ion);
> =A0 =A0 =A0 =A0}
> =A0}
>
> @@ -209,6 +212,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev=
)
> =A0 =A0 =A0 =A0struct pci_bus *bus;
> =A0 =A0 =A0 =A0const u32 *busrange, *ranges;
> =A0 =A0 =A0 =A0int len, i, mode;
> + =A0 =A0 =A0 struct pci_bus_region region;
> =A0 =A0 =A0 =A0struct resource *res;
> =A0 =A0 =A0 =A0unsigned int flags;
> =A0 =A0 =A0 =A0u64 size;
> @@ -270,9 +274,10 @@ void __devinit of_scan_pci_bridge(struct pci_dev *de=
v)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0res =3D bus->resource[i];
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0++i;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 res->start =3D of_read_number(&ranges[1], 2=
);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 res->end =3D res->start + size - 1;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0res->flags =3D flags;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 region.start =3D of_read_number(&ranges[1],=
2);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 region.end =3D region.start + size - 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pcibios_bus_to_resource(dev, res, ®ion);
> =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus)=
,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bus->number);
>
>
^ permalink raw reply
* Re: tlb flushing on Power
From: Seth Jennings @ 2012-03-05 17:56 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Robert Jennings, linuxppc-dev, Nitin Gupta, Dave Hansen
In-Reply-To: <1329424301.2892.23.camel@pasglop>
Hey Ben,
Thanks for the help! I was wondering if you could take a look at something
for me.
I've been working on this staging driver (zsmalloc memory allocator)
that does virtual mapping of two pages.
I have a github repo with the driver and the unsubmitted changes. I'm
trying to make to get the pte/tlb stuff working in a portable way:
git://github.com/spartacus06/linux.git (portable branch)
The experimental commits are the top 5 and the branch is based on
Greg's staging-next + frontswap-v11 patches.
Could you take a look at the zs_map_object() and zs_unmap_object()
in drivers/staging/zsmalloc/zsmalloc-main.c and see if they should
work for PPC64?
I'm using set_pte_at() to map. Then I'm using and ptep_get_and_clear()
and local_flush_tlb_kernel_page() to unmap (I #defined
local_flush_tlb_kernel_page() to local_flush_tlb_page() for PPC64 which
is a no-op).
It will work most of the time, but then I'll get a crash and the
mapped memory won't be what I expect. I know the cause lies in the
virtual mapping because if I reduce the max_zspage_order to
1, preventing the "else" branch in zs_[un]map_object() from being
called, everything is stable.
Any feedback you (or others) can provide would be appreciated!
Thanks,
Seth
On 02/16/2012 02:31 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2012-02-16 at 11:11 -0600, Seth Jennings wrote:
>
>> Just wanted to bump you again about this. You mentioned that if I wanted to
>> do a cpu-local flush of a single tlb entry, that there would have to be a new
>> hook. Is that right?
>>
>> I've been looking through the powerpc arch and I thought that I might have
>> found the power analog to __flush_tlb_one() for x86 in local_flush_tlb_page()
>> with a NULL vma argument. This doesn't seem to work though, as indicated
>> by a crash when I tried it. After looking in tlbflush.h again, it seems
>> that local_flush_tlb_page() is a no-op when CONFIG_PPC_STD_MMU_64 is set,
>> as are almost ALL of the tlb flushing functions... which makes no sense to
>> me.
>>
>> Any help you (or anyone) can give me would be greatly appreciated.
>
> On ppc64 with hash-table MMU, we handle the flushes very differently.
> PTEs that are modified are added to a list at the time of the
> modification and either flushed immediately if no lazy tlb batching is
> in progress or flushed when leaving the lazy tlb op.
>
> This is to avoid a problem where we might otherwise, under some
> circumstances, create a new TLB which can be hashed in to the hash table
> before the previous one has been flushed out. That would lead to a dup
> in the hash table which is architecturally illegal.
>
> This happens via the call to hpte_need_flush() in pte_update().
>
> Unfortunately, it will always consider all kernel mappings as global,
> so the per-cpu "optimization" won't be usable in this case, at least
> not until we add some kind of additional argument to that function.
>
> Cheers,
> Ben.
>
>
^ permalink raw reply
* [PATCH 0/9] DMA engine cookie handling cleanups
From: Russell King - ARM Linux @ 2012-03-05 20:14 UTC (permalink / raw)
To: Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, Barry Song, linuxppc-dev, linux-arm-kernel
This patch series cleans up the handling of cookies in DMA engine drivers.
This is done by providing a set of inline library functions for common
tasks:
- moving the 'last completed cookie' into struct dma_chan - everyone
has this in their driver private channel data structure
- consolidate allocation of cookies to DMA descriptors
- common way to update 'last completed cookie' value
- standard way to implement tx_status callback and update the residue
- consolidate initialization of cookies
- update implementations differing from the majority of DMA engine drivers
to behave the same as the majority implementation in respect of cookies
What this means is that we get to the point where all DMA engine drivers
will hand out cookie value '2' as the first, and incrementing cookie
values up to INT_MAX, returning to cookie '1' as the next cookie.
Think of this patch series as round 1... I am hoping over time that more
code can be consolidated between the DMA engine drivers and end up with a
consistent way to handle various common themes in DMA engine hardware
(like physical channel<->peripheral request signal selection.)
I've only build-tested this stuff on a few ARM configs, and my ability
to run-test this stuff is even more limited by all the broken useless DMA
engine hardware I have access to (mostly pl08x based) so having some
tested-bys would be a great advantage.
Overall, the diffstat looks like this:
arch/arm/include/asm/hardware/iop_adma.h | 2 -
drivers/dma/amba-pl08x.c | 38 ++++---------
drivers/dma/at_hdmac.c | 48 ++++------------
drivers/dma/at_hdmac_regs.h | 2 -
drivers/dma/coh901318.c | 39 +++----------
drivers/dma/dmaengine.h | 89 ++++++++++++++++++++++++++++++
drivers/dma/dw_dmac.c | 43 +++-----------
drivers/dma/dw_dmac_regs.h | 1 -
drivers/dma/ep93xx_dma.c | 25 ++------
drivers/dma/fsldma.c | 24 ++------
drivers/dma/fsldma.h | 1 -
drivers/dma/imx-dma.c | 32 ++---------
drivers/dma/imx-sdma.c | 23 ++------
drivers/dma/intel_mid_dma.c | 37 +++---------
drivers/dma/intel_mid_dma_regs.h | 2 -
drivers/dma/ioat/dma.c | 21 +++----
drivers/dma/ioat/dma.h | 23 --------
drivers/dma/ioat/dma_v2.c | 13 ++---
drivers/dma/ioat/dma_v3.c | 11 ++--
drivers/dma/iop-adma.c | 51 ++++-------------
drivers/dma/ipu/ipu_idmac.c | 22 ++-----
drivers/dma/mpc512x_dma.c | 25 +++------
drivers/dma/mv_xor.c | 34 ++---------
drivers/dma/mv_xor.h | 3 -
drivers/dma/mxs-dma.c | 23 ++------
drivers/dma/pch_dma.c | 34 ++---------
drivers/dma/pl330.c | 36 ++----------
drivers/dma/ppc4xx/adma.c | 49 +++-------------
drivers/dma/ppc4xx/adma.h | 2 -
drivers/dma/shdma.c | 30 +++-------
drivers/dma/shdma.h | 1 -
drivers/dma/sirf-dma.c | 23 ++------
drivers/dma/ste_dma40.c | 36 +++---------
drivers/dma/timb_dma.c | 28 +++-------
drivers/dma/txx9dmac.c | 41 +++-----------
drivers/dma/txx9dmac.h | 1 -
include/linux/amba/pl08x.h | 2 -
include/linux/dmaengine.h | 2 +
38 files changed, 291 insertions(+), 626 deletions(-)
^ permalink raw reply
* Re: [PATCH] rapidio/tsi721: fix bug in inbound doorbell handler
From: Andrew Morton @ 2012-03-05 20:37 UTC (permalink / raw)
To: Alexandre Bounine; +Cc: Chul Kim, linuxppc-dev, linux-kernel
In-Reply-To: <1330979585-29429-1-git-send-email-alexandre.bounine@idt.com>
On Mon, 5 Mar 2012 15:33:05 -0500
Alexandre Bounine <alexandre.bounine@idt.com> wrote:
> Fixes queue wrapping bug in Inbound Doorbell handling routine.
The changelog doesn't describe the user-visible impact of the bug.
Please always include this so that people know whether to backport the
fix into their kernels, and so they can determine whether the patch
will fix a problem which they are observing.
^ permalink raw reply
* [PATCH 6/9] dmaengine: consolidate tx_status functions
From: Russell King - ARM Linux @ 2012-03-05 20:16 UTC (permalink / raw)
To: Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, Barry Song, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20120305201411.GA17791@n2100.arm.linux.org.uk>
Now that we have the completed cookie in the dma_chan structure, we
can consolidate the tx_status functions by providing a function to set
the txstate structure and returning the DMA status. We also provide
a separate helper to set the residue for cookies which are still in
progress.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/amba-pl08x.c | 22 ++++------------------
drivers/dma/at_hdmac.c | 18 ++++++------------
drivers/dma/coh901318.c | 13 ++++---------
drivers/dma/dmaengine.h | 31 +++++++++++++++++++++++++++++++
drivers/dma/dw_dmac.c | 19 ++++---------------
drivers/dma/ep93xx_dma.c | 7 +------
drivers/dma/fsldma.c | 11 +++--------
drivers/dma/imx-dma.c | 11 +----------
drivers/dma/intel_mid_dma.c | 19 +++----------------
drivers/dma/ioat/dma.c | 8 +++++---
drivers/dma/ioat/dma.h | 21 ---------------------
drivers/dma/ioat/dma_v3.c | 8 +++++---
drivers/dma/iop-adma.c | 16 +++-------------
drivers/dma/mpc512x_dma.c | 9 +++------
drivers/dma/mv_xor.c | 14 ++------------
drivers/dma/pch_dma.c | 11 ++---------
drivers/dma/pl330.c | 13 +------------
drivers/dma/ppc4xx/adma.c | 16 ++--------------
drivers/dma/shdma.c | 11 +----------
drivers/dma/sirf-dma.c | 9 +++------
drivers/dma/ste_dma40.c | 14 ++++----------
drivers/dma/timb_dma.c | 11 ++---------
drivers/dma/txx9dmac.c | 16 +++-------------
23 files changed, 93 insertions(+), 235 deletions(-)
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index f0888c1..2781a2b 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -964,31 +964,17 @@ static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *txstate)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
enum dma_status ret;
- u32 bytesleft = 0;
- last_used = plchan->chan.cookie;
- last_complete = plchan->chan.completed_cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
- if (ret == DMA_SUCCESS) {
- dma_set_tx_state(txstate, last_complete, last_used, 0);
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_SUCCESS)
return ret;
- }
/*
* This cookie not complete yet
+ * Get number of bytes left in the active transactions and queue
*/
- last_used = plchan->chan.cookie;
- last_complete = plchan->chan.completed_cookie;
-
- /* Get number of bytes left in the active transactions and queue */
- bytesleft = pl08x_getbytes_chan(plchan);
-
- dma_set_tx_state(txstate, last_complete, last_used,
- bytesleft);
+ dma_set_residue(txstate, pl08x_getbytes_chan(plchan));
if (plchan->state == PL08X_CHAN_PAUSED)
return DMA_PAUSED;
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index b282630..8a32974 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -996,26 +996,20 @@ atc_tx_status(struct dma_chan *chan,
spin_lock_irqsave(&atchan->lock, flags);
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
if (ret != DMA_SUCCESS) {
atc_cleanup_descriptors(atchan);
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
}
+ last_complete = chan->completed_cookie;
+ last_used = chan->cookie;
+
spin_unlock_irqrestore(&atchan->lock, flags);
if (ret != DMA_SUCCESS)
- dma_set_tx_state(txstate, last_complete, last_used,
- atc_first_active(atchan)->len);
- else
- dma_set_tx_state(txstate, last_complete, last_used, 0);
+ dma_set_residue(txstate, atc_first_active(atchan)->len);
if (atc_chan_is_paused(atchan))
ret = DMA_PAUSED;
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 24837d7..f350517 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -1151,17 +1151,12 @@ coh901318_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
struct coh901318_chan *cohc = to_coh901318_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- int ret;
-
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
+ enum dma_status ret;
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
+ /* FIXME: should be conditional on ret != DMA_SUCCESS? */
+ dma_set_residue(txstate, coh901318_get_bytes_left(chan));
- dma_set_tx_state(txstate, last_complete, last_used,
- coh901318_get_bytes_left(chan));
if (ret == DMA_IN_PROGRESS && cohc->stopped)
ret = DMA_PAUSED;
diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
index 47e0997..244a2c5 100644
--- a/drivers/dma/dmaengine.h
+++ b/drivers/dma/dmaengine.h
@@ -45,4 +45,35 @@ static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx)
tx->cookie = 0;
}
+/**
+ * dma_cookie_status - report cookie status
+ * @chan: dma channel
+ * @cookie: cookie we are interested in
+ * @state: dma_tx_state structure to return last/used cookies
+ *
+ * Report the status of the cookie, filling in the state structure if
+ * non-NULL. No locking is required.
+ */
+static inline enum dma_status dma_cookie_status(struct dma_chan *chan,
+ dma_cookie_t cookie, struct dma_tx_state *state)
+{
+ dma_cookie_t used, complete;
+
+ used = chan->cookie;
+ complete = chan->complete;
+ barrier();
+ if (state) {
+ state->last = complete;
+ state->used = used;
+ state->residue = 0;
+ }
+ return dma_async_is_complete(cookie, complete, used);
+}
+
+static inline void dma_set_residue(struct dma_tx_state *state, u32 residue)
+{
+ if (state)
+ state->residue = residue;
+}
+
#endif
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index a190c88..acc3bc0 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -937,28 +937,17 @@ dwc_tx_status(struct dma_chan *chan,
struct dma_tx_state *txstate)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- int ret;
+ enum dma_status ret;
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
if (ret != DMA_SUCCESS) {
dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
}
if (ret != DMA_SUCCESS)
- dma_set_tx_state(txstate, last_complete, last_used,
- dwc_first_active(dwc)->len);
- else
- dma_set_tx_state(txstate, last_complete, last_used, 0);
+ dma_set_residue(txstate, dwc_first_active(dwc)->len);
if (dwc->paused)
return DMA_PAUSED;
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 1c56f75..142ebf0 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -1241,18 +1241,13 @@ static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
struct dma_tx_state *state)
{
struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
- dma_cookie_t last_used, last_completed;
enum dma_status ret;
unsigned long flags;
spin_lock_irqsave(&edmac->lock, flags);
- last_used = chan->cookie;
- last_completed = chan->completed_cookie;
+ ret = dma_cookie_status(chan, cookie, state);
spin_unlock_irqrestore(&edmac->lock, flags);
- ret = dma_async_is_complete(cookie, last_completed, last_used);
- dma_set_tx_state(state, last_completed, last_used, 0);
-
return ret;
}
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index f36e8b1..2f6c806 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -978,19 +978,14 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
struct dma_tx_state *txstate)
{
struct fsldma_chan *chan = to_fsl_chan(dchan);
- dma_cookie_t last_complete;
- dma_cookie_t last_used;
+ enum dma_status ret;
unsigned long flags;
spin_lock_irqsave(&chan->desc_lock, flags);
-
- last_complete = dchan->completed_cookie;
- last_used = dchan->cookie;
-
+ ret = dma_cookie_status(dchan, cookie, txstate);
spin_unlock_irqrestore(&chan->desc_lock, flags);
- dma_set_tx_state(txstate, last_complete, last_used, 0);
- return dma_async_is_complete(cookie, last_complete, last_used);
+ return ret;
}
/*----------------------------------------------------------------------------*/
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index f1226ad..ba317e6 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -153,16 +153,7 @@ static enum dma_status imxdma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
- struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
- dma_cookie_t last_used;
- enum dma_status ret;
-
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, chan->completed_cookie, last_used);
- dma_set_tx_state(txstate, chan->completed_cookie, last_used, 0);
-
- return ret;
+ return dma_cookie_status(chan, cookie, txstate);
}
static dma_cookie_t imxdma_tx_submit(struct dma_async_tx_descriptor *tx)
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index 340509e..69ed1e6 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -477,30 +477,17 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- int ret;
+ enum dma_status ret;
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
if (ret != DMA_SUCCESS) {
spin_lock_bh(&midc->lock);
midc_scan_descriptors(to_middma_device(chan->device), midc);
spin_unlock_bh(&midc->lock);
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
}
- if (txstate) {
- txstate->last = last_complete;
- txstate->used = last_used;
- txstate->residue = 0;
- }
return ret;
}
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index b0517c8..97e100c 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -729,13 +729,15 @@ ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
{
struct ioat_chan_common *chan = to_chan_common(c);
struct ioatdma_device *device = chan->device;
+ enum dma_status ret;
- if (ioat_tx_status(c, cookie, txstate) == DMA_SUCCESS)
- return DMA_SUCCESS;
+ ret = dma_cookie_status(c, cookie, txstate);
+ if (ret == DMA_SUCCESS)
+ return ret;
device->cleanup_fn((unsigned long) c);
- return ioat_tx_status(c, cookie, txstate);
+ return dma_cookie_status(c, cookie, txstate);
}
static void ioat1_dma_start_null_desc(struct ioat_dma_chan *ioat)
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index 9653b6b..c7888bc 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -142,27 +142,6 @@ static inline struct ioat_dma_chan *to_ioat_chan(struct dma_chan *c)
return container_of(chan, struct ioat_dma_chan, base);
}
-/**
- * ioat_tx_status - poll the status of an ioat transaction
- * @c: channel handle
- * @cookie: transaction identifier
- * @txstate: if set, updated with the transaction state
- */
-static inline enum dma_status
-ioat_tx_status(struct dma_chan *c, dma_cookie_t cookie,
- struct dma_tx_state *txstate)
-{
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
-
- last_used = c->cookie;
- last_complete = c->completed_cookie;
-
- dma_set_tx_state(txstate, last_complete, last_used, 0);
-
- return dma_async_is_complete(cookie, last_complete, last_used);
-}
-
/* wrapper around hardware descriptor format + additional software fields */
/**
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index 1bda46c..145eda2 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -410,13 +410,15 @@ ioat3_tx_status(struct dma_chan *c, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
+ enum dma_status ret;
- if (ioat_tx_status(c, cookie, txstate) == DMA_SUCCESS)
- return DMA_SUCCESS;
+ ret = dma_cookie_status(c, cookie, txstate);
+ if (ret == DMA_SUCCESS)
+ return ret;
ioat3_cleanup(ioat);
- return ioat_tx_status(c, cookie, txstate);
+ return dma_cookie_status(c, cookie, txstate);
}
static struct dma_async_tx_descriptor *
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index f2392d5..b1e3be08 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -894,24 +894,14 @@ static enum dma_status iop_adma_status(struct dma_chan *chan,
struct dma_tx_state *txstate)
{
struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- enum dma_status ret;
-
- last_used = chan->cookie;
- last_complete = chan->completed_cookie;
- dma_set_tx_state(txstate, last_complete, last_used, 0);
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+
+ ret = dma_cookie_status(chan, cookie, txstate);
if (ret == DMA_SUCCESS)
return ret;
iop_adma_slot_cleanup(iop_chan);
- last_used = chan->cookie;
- last_complete = chan->completed_cookie;
- dma_set_tx_state(txstate, last_complete, last_used, 0);
-
- return dma_async_is_complete(cookie, last_complete, last_used);
+ return dma_cookie_status(chan, cookie, txstate);
}
static irqreturn_t iop_adma_eot_handler(int irq, void *data)
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 0253d5a..1382715 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -557,17 +557,14 @@ mpc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+ enum dma_status ret;
unsigned long flags;
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
spin_lock_irqsave(&mchan->lock, flags);
- last_used = mchan->chan.cookie;
- last_complete = mchan->chan.completed_cookie;
+ ret = dma_cookie_status(chan, cookie, txstate);
spin_unlock_irqrestore(&mchan->lock, flags);
- dma_set_tx_state(txstate, last_complete, last_used, 0);
- return dma_async_is_complete(cookie, last_complete, last_used);
+ return ret;
}
/* Prepare descriptor for memory to memory copy */
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index d9810ce..486353e 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -810,26 +810,16 @@ static enum dma_status mv_xor_status(struct dma_chan *chan,
struct dma_tx_state *txstate)
{
struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
enum dma_status ret;
- last_used = chan->cookie;
- last_complete = chan->completed_cookie;
- dma_set_tx_state(txstate, last_complete, last_used, 0);
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
if (ret == DMA_SUCCESS) {
mv_xor_clean_completed_slots(mv_chan);
return ret;
}
mv_xor_slot_cleanup(mv_chan);
- last_used = chan->cookie;
- last_complete = chan->completed_cookie;
-
- dma_set_tx_state(txstate, last_complete, last_used, 0);
- return dma_async_is_complete(cookie, last_complete, last_used);
+ return dma_cookie_status(chan, cookie, txstate);
}
static void mv_dump_xor_regs(struct mv_xor_chan *chan)
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 5218e48..c30f63e 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -565,19 +565,12 @@ static enum dma_status pd_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
struct pch_dma_chan *pd_chan = to_pd_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_completed;
- int ret;
+ enum dma_status ret;
spin_lock_irq(&pd_chan->lock);
- last_completed = chan->completed_cookie;
- last_used = chan->cookie;
+ ret = dma_cookie_status(chan, cookie, txstate);
spin_unlock_irq(&pd_chan->lock);
- ret = dma_async_is_complete(cookie, last_completed, last_used);
-
- dma_set_tx_state(txstate, last_completed, last_used, 0);
-
return ret;
}
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 76871b8..1993286 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -395,18 +395,7 @@ static enum dma_status
pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
- struct dma_pl330_chan *pch = to_pchan(chan);
- dma_cookie_t last_done, last_used;
- int ret;
-
- last_done = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_done, last_used);
-
- dma_set_tx_state(txstate, last_done, last_used, 0);
-
- return ret;
+ return dma_cookie_status(chan, cookie, txstate);
}
static void pl330_issue_pending(struct dma_chan *chan)
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 12e94dd..86239ea 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -3928,28 +3928,16 @@ static enum dma_status ppc440spe_adma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *txstate)
{
struct ppc440spe_adma_chan *ppc440spe_chan;
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
enum dma_status ret;
ppc440spe_chan = to_ppc440spe_adma_chan(chan);
- last_used = chan->cookie;
- last_complete = chan->completed_cookie;
-
- dma_set_tx_state(txstate, last_complete, last_used, 0);
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
if (ret == DMA_SUCCESS)
return ret;
ppc440spe_adma_slot_cleanup(ppc440spe_chan);
- last_used = chan->cookie;
- last_complete = chan->completed_cookie;
-
- dma_set_tx_state(txstate, last_complete, last_used, 0);
-
- return dma_async_is_complete(cookie, last_complete, last_used);
+ return dma_cookie_status(chan, cookie, txstate);
}
/**
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 96d0a4f..50510ef 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -879,23 +879,14 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
struct dma_tx_state *txstate)
{
struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
enum dma_status status;
unsigned long flags;
sh_dmae_chan_ld_cleanup(sh_chan, false);
- /* First read completed cookie to avoid a skew */
- last_complete = chan->completed_cookie;
- rmb();
- last_used = chan->cookie;
- BUG_ON(last_complete < 0);
- dma_set_tx_state(txstate, last_complete, last_used, 0);
-
spin_lock_irqsave(&sh_chan->desc_lock, flags);
- status = dma_async_is_complete(cookie, last_complete, last_used);
+ status = dma_cookie_status(chan, cookie, txstate);
/*
* If we don't find cookie on the queue, it has been aborted and we have
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 7bb154a..a760d98 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -407,16 +407,13 @@ sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
{
struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
unsigned long flags;
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
+ enum dma_status ret;
spin_lock_irqsave(&schan->lock, flags);
- last_used = schan->chan.cookie;
- last_complete = schan->chan.completed_cookie;
+ ret = dma_cookie_status(chan, cookie, txstate);
spin_unlock_irqrestore(&schan->lock, flags);
- dma_set_tx_state(txstate, last_complete, last_used, 0);
- return dma_async_is_complete(cookie, last_complete, last_used);
+ return ret;
}
static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index c246375..07b82e3 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2332,25 +2332,19 @@ static enum dma_status d40_tx_status(struct dma_chan *chan,
struct dma_tx_state *txstate)
{
struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- int ret;
+ enum dma_status ret;
if (d40c->phy_chan == NULL) {
chan_err(d40c, "Cannot read status of unallocated channel\n");
return -EINVAL;
}
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret != DMA_SUCCESS)
+ dma_set_residue(txstate, stedma40_residue(chan));
if (d40_is_paused(d40c))
ret = DMA_PAUSED;
- else
- ret = dma_async_is_complete(cookie, last_complete, last_used);
-
- dma_set_tx_state(txstate, last_complete, last_used,
- stedma40_residue(chan));
return ret;
}
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 1845ac9..6383abb 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -513,18 +513,11 @@ static enum dma_status td_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
{
struct timb_dma_chan *td_chan =
container_of(chan, struct timb_dma_chan, chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- int ret;
+ enum dma_status ret;
dev_dbg(chan2dev(chan), "%s: Entry\n", __func__);
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
-
- dma_set_tx_state(txstate, last_complete, last_used, 0);
+ ret = dma_cookie_status(chan, cookie, txstate);
dev_dbg(chan2dev(chan),
"%s: exit, ret: %d, last_complete: %d, last_used: %d\n",
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 8a5225b..bb7b3d9 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -959,27 +959,17 @@ txx9dmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
- dma_cookie_t last_used;
- dma_cookie_t last_complete;
- int ret;
+ enum dma_status ret;
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
if (ret != DMA_SUCCESS) {
spin_lock_bh(&dc->lock);
txx9dmac_scan_descriptors(dc);
spin_unlock_bh(&dc->lock);
- last_complete = chan->completed_cookie;
- last_used = chan->cookie;
-
- ret = dma_async_is_complete(cookie, last_complete, last_used);
+ ret = dma_cookie_status(chan, cookie, txstate);
}
- dma_set_tx_state(txstate, last_complete, last_used, 0);
-
return ret;
}
--
1.7.4.4
^ permalink raw reply related
* [PATCH 2/9] dmaengine: move last completed cookie into generic dma_chan structure
From: Russell King - ARM Linux @ 2012-03-05 20:15 UTC (permalink / raw)
To: Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, Barry Song, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20120305201411.GA17791@n2100.arm.linux.org.uk>
Every DMA engine implementation declares a last completed dma cookie
in their private dma channel structures. This is pointless, and
forces driver specific code. Move this out into the common dma_chan
structure.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/include/asm/hardware/iop_adma.h | 2 --
drivers/dma/amba-pl08x.c | 8 ++++----
drivers/dma/at_hdmac.c | 10 +++++-----
drivers/dma/at_hdmac_regs.h | 2 --
drivers/dma/coh901318.c | 7 +++----
drivers/dma/dw_dmac.c | 10 +++++-----
drivers/dma/dw_dmac_regs.h | 1 -
drivers/dma/ep93xx_dma.c | 8 +++-----
drivers/dma/fsldma.c | 4 ++--
drivers/dma/fsldma.h | 1 -
drivers/dma/imx-dma.c | 7 +++----
drivers/dma/imx-sdma.c | 5 ++---
drivers/dma/intel_mid_dma.c | 9 ++++-----
drivers/dma/intel_mid_dma_regs.h | 2 --
drivers/dma/ioat/dma.c | 2 +-
drivers/dma/ioat/dma.h | 4 +---
drivers/dma/ioat/dma_v2.c | 2 +-
drivers/dma/ioat/dma_v3.c | 2 +-
drivers/dma/iop-adma.c | 10 +++++-----
drivers/dma/ipu/ipu_idmac.c | 10 ++++------
drivers/dma/mpc512x_dma.c | 7 +++----
drivers/dma/mv_xor.c | 6 +++---
drivers/dma/mv_xor.h | 2 --
drivers/dma/mxs-dma.c | 5 ++---
drivers/dma/pch_dma.c | 5 ++---
drivers/dma/pl330.c | 9 +++------
drivers/dma/ppc4xx/adma.c | 10 +++++-----
drivers/dma/ppc4xx/adma.h | 2 --
drivers/dma/shdma.c | 10 +++++-----
drivers/dma/shdma.h | 1 -
drivers/dma/sirf-dma.c | 7 +++----
drivers/dma/ste_dma40.c | 10 +++-------
drivers/dma/timb_dma.c | 7 +++----
drivers/dma/txx9dmac.c | 10 +++++-----
drivers/dma/txx9dmac.h | 1 -
include/linux/amba/pl08x.h | 2 --
include/linux/dmaengine.h | 2 ++
37 files changed, 83 insertions(+), 119 deletions(-)
diff --git a/arch/arm/include/asm/hardware/iop_adma.h b/arch/arm/include/asm/hardware/iop_adma.h
index 59b8c38..122f86d 100644
--- a/arch/arm/include/asm/hardware/iop_adma.h
+++ b/arch/arm/include/asm/hardware/iop_adma.h
@@ -49,7 +49,6 @@ struct iop_adma_device {
/**
* struct iop_adma_chan - internal representation of an ADMA device
* @pending: allows batching of hardware operations
- * @completed_cookie: identifier for the most recently completed operation
* @lock: serializes enqueue/dequeue operations to the slot pool
* @mmr_base: memory mapped register base
* @chain: device chain view of the descriptors
@@ -62,7 +61,6 @@ struct iop_adma_device {
*/
struct iop_adma_chan {
int pending;
- dma_cookie_t completed_cookie;
spinlock_t lock; /* protects the descriptor slot pool */
void __iomem *mmr_base;
struct list_head chain;
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 8a28158..2b5121f 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -971,7 +971,7 @@ static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
u32 bytesleft = 0;
last_used = plchan->chan.cookie;
- last_complete = plchan->lc;
+ last_complete = plchan->chan.completed_cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
if (ret == DMA_SUCCESS) {
@@ -983,7 +983,7 @@ static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
* This cookie not complete yet
*/
last_used = plchan->chan.cookie;
- last_complete = plchan->lc;
+ last_complete = plchan->chan.completed_cookie;
/* Get number of bytes left in the active transactions and queue */
bytesleft = pl08x_getbytes_chan(plchan);
@@ -1541,7 +1541,7 @@ static void pl08x_tasklet(unsigned long data)
if (txd) {
/* Update last completed */
- plchan->lc = txd->tx.cookie;
+ plchan->chan.completed_cookie = txd->tx.cookie;
}
/* If a new descriptor is queued, set it up plchan->at is NULL here */
@@ -1723,7 +1723,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
chan->chan.device = dmadev;
chan->chan.cookie = 0;
- chan->lc = 0;
+ chan->chan.completed_cookie = 0;
spin_lock_init(&chan->lock);
INIT_LIST_HEAD(&chan->pend_list);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index f4aed5f..6baf5d7 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -269,7 +269,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
dev_vdbg(chan2dev(&atchan->chan_common),
"descriptor %u complete\n", txd->cookie);
- atchan->completed_cookie = txd->cookie;
+ atchan->chan_common.completed_cookie = txd->cookie;
/* move children to free_list */
list_splice_init(&desc->tx_list, &atchan->free_list);
@@ -1016,14 +1016,14 @@ atc_tx_status(struct dma_chan *chan,
spin_lock_irqsave(&atchan->lock, flags);
- last_complete = atchan->completed_cookie;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
if (ret != DMA_SUCCESS) {
atc_cleanup_descriptors(atchan);
- last_complete = atchan->completed_cookie;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -1129,7 +1129,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
spin_lock_irqsave(&atchan->lock, flags);
atchan->descs_allocated = i;
list_splice(&tmp_list, &atchan->free_list);
- atchan->completed_cookie = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
spin_unlock_irqrestore(&atchan->lock, flags);
/* channel parameters */
@@ -1329,7 +1329,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
struct at_dma_chan *atchan = &atdma->chan[i];
atchan->chan_common.device = &atdma->dma_common;
- atchan->chan_common.cookie = atchan->completed_cookie = 1;
+ atchan->chan_common.cookie = atchan->chan_common.completed_cookie = 1;
list_add_tail(&atchan->chan_common.device_node,
&atdma->dma_common.channels);
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index a8d3277..08fd8a0 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -208,7 +208,6 @@ enum atc_status {
* @save_dscr: for cyclic operations, preserve next descriptor address in
* the cyclic list on suspend/resume cycle
* @lock: serializes enqueue/dequeue operations to descriptors lists
- * @completed_cookie: identifier for the most recently completed operation
* @active_list: list of descriptors dmaengine is being running on
* @queue: list of descriptors ready to be submitted to engine
* @free_list: list of descriptors usable by the channel
@@ -227,7 +226,6 @@ struct at_dma_chan {
spinlock_t lock;
/* these other elements are all protected by lock */
- dma_cookie_t completed_cookie;
struct list_head active_list;
struct list_head queue;
struct list_head free_list;
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index d65a718..521434b 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -59,7 +59,6 @@ struct coh901318_base {
struct coh901318_chan {
spinlock_t lock;
int allocated;
- int completed;
int id;
int stopped;
@@ -705,7 +704,7 @@ static void dma_tasklet(unsigned long data)
callback_param = cohd_fin->desc.callback_param;
/* sign this job as completed on the channel */
- cohc->completed = cohd_fin->desc.cookie;
+ cohc->chan.completed_cookie = cohd_fin->desc.cookie;
/* release the lli allocation and remove the descriptor */
coh901318_lli_free(&cohc->base->pool, &cohd_fin->lli);
@@ -929,7 +928,7 @@ static int coh901318_alloc_chan_resources(struct dma_chan *chan)
coh901318_config(cohc, NULL);
cohc->allocated = 1;
- cohc->completed = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
spin_unlock_irqrestore(&cohc->lock, flags);
@@ -1169,7 +1168,7 @@ coh901318_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
dma_cookie_t last_complete;
int ret;
- last_complete = cohc->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 9b592b0..defe574 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -245,7 +245,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc,
dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);
spin_lock_irqsave(&dwc->lock, flags);
- dwc->completed = txd->cookie;
+ dwc->chan.completed_cookie = txd->cookie;
if (callback_required) {
callback = txd->callback;
param = txd->callback_param;
@@ -955,14 +955,14 @@ dwc_tx_status(struct dma_chan *chan,
dma_cookie_t last_complete;
int ret;
- last_complete = dwc->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
if (ret != DMA_SUCCESS) {
dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
- last_complete = dwc->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -1004,7 +1004,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
return -EIO;
}
- dwc->completed = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
/*
* NOTE: some controllers may have additional features that we
@@ -1423,7 +1423,7 @@ static int __init dw_probe(struct platform_device *pdev)
struct dw_dma_chan *dwc = &dw->chan[i];
dwc->chan.device = &dw->dma;
- dwc->chan.cookie = dwc->completed = 1;
+ dwc->chan.cookie = dwc->chan.completed_cookie = 1;
if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
list_add_tail(&dwc->chan.device_node,
&dw->dma.channels);
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 5eef694..cce1752 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -146,7 +146,6 @@ struct dw_dma_chan {
/* these other elements are all protected by lock */
unsigned long flags;
- dma_cookie_t completed;
struct list_head active_list;
struct list_head queue;
struct list_head free_list;
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 59e7a96..bc45787 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -122,7 +122,6 @@ struct ep93xx_dma_desc {
* @lock: lock protecting the fields following
* @flags: flags for the channel
* @buffer: which buffer to use next (0/1)
- * @last_completed: last completed cookie value
* @active: flattened chain of descriptors currently being processed
* @queue: pending descriptors which are handled next
* @free_list: list of free descriptors which can be used
@@ -157,7 +156,6 @@ struct ep93xx_dma_chan {
#define EP93XX_DMA_IS_CYCLIC 0
int buffer;
- dma_cookie_t last_completed;
struct list_head active;
struct list_head queue;
struct list_head free_list;
@@ -703,7 +701,7 @@ static void ep93xx_dma_tasklet(unsigned long data)
desc = ep93xx_dma_get_active(edmac);
if (desc) {
if (desc->complete) {
- edmac->last_completed = desc->txd.cookie;
+ edmac->chan.completed_cookie = desc->txd.cookie;
list_splice_init(&edmac->active, &list);
}
callback = desc->txd.callback;
@@ -861,7 +859,7 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
goto fail_clk_disable;
spin_lock_irq(&edmac->lock);
- edmac->last_completed = 1;
+ edmac->chan.completed_cookie = 1;
edmac->chan.cookie = 1;
ret = edmac->edma->hw_setup(edmac);
spin_unlock_irq(&edmac->lock);
@@ -1254,7 +1252,7 @@ static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
spin_lock_irqsave(&edmac->lock, flags);
last_used = chan->cookie;
- last_completed = edmac->last_completed;
+ last_completed = chan->completed_cookie;
spin_unlock_irqrestore(&edmac->lock, flags);
ret = dma_async_is_complete(cookie, last_completed, last_used);
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index b98070c..9b5cb8a 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -990,7 +990,7 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
spin_lock_irqsave(&chan->desc_lock, flags);
- last_complete = chan->completed_cookie;
+ last_complete = dchan->completed_cookie;
last_used = dchan->cookie;
spin_unlock_irqrestore(&chan->desc_lock, flags);
@@ -1088,7 +1088,7 @@ static void dma_do_tasklet(unsigned long data)
desc = to_fsl_desc(chan->ld_running.prev);
cookie = desc->async_tx.cookie;
- chan->completed_cookie = cookie;
+ chan->common.completed_cookie = cookie;
chan_dbg(chan, "completed_cookie=%d\n", cookie);
}
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index 9cb5aa5..f5c3879 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -137,7 +137,6 @@ struct fsldma_device {
struct fsldma_chan {
char name[8]; /* Channel name */
struct fsldma_chan_regs __iomem *regs;
- dma_cookie_t completed_cookie; /* The maximum cookie completed */
spinlock_t desc_lock; /* Descriptor operation lock */
struct list_head ld_pending; /* Link descriptors queue */
struct list_head ld_running; /* Link descriptors queue */
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index e4383ee..321fc1f 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -41,7 +41,6 @@ struct imxdma_channel {
struct dma_chan chan;
spinlock_t lock;
struct dma_async_tx_descriptor desc;
- dma_cookie_t last_completed;
enum dma_status status;
int dma_request;
struct scatterlist *sg_list;
@@ -65,7 +64,7 @@ static void imxdma_handle(struct imxdma_channel *imxdmac)
{
if (imxdmac->desc.callback)
imxdmac->desc.callback(imxdmac->desc.callback_param);
- imxdmac->last_completed = imxdmac->desc.cookie;
+ imxdmac->chan.completed_cookie = imxdmac->desc.cookie;
}
static void imxdma_irq_handler(int channel, void *data)
@@ -158,8 +157,8 @@ static enum dma_status imxdma_tx_status(struct dma_chan *chan,
last_used = chan->cookie;
- ret = dma_async_is_complete(cookie, imxdmac->last_completed, last_used);
- dma_set_tx_state(txstate, imxdmac->last_completed, last_used, 0);
+ ret = dma_async_is_complete(cookie, chan->completed_cookie, last_used);
+ dma_set_tx_state(txstate, chan->completed_cookie, last_used, 0);
return ret;
}
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 8bc5acf..e857904 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -266,7 +266,6 @@ struct sdma_channel {
struct dma_chan chan;
spinlock_t lock;
struct dma_async_tx_descriptor desc;
- dma_cookie_t last_completed;
enum dma_status status;
unsigned int chn_count;
unsigned int chn_real_count;
@@ -523,7 +522,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
else
sdmac->status = DMA_SUCCESS;
- sdmac->last_completed = sdmac->desc.cookie;
+ sdmac->chan.completed_cookie = sdmac->desc.cookie;
if (sdmac->desc.callback)
sdmac->desc.callback(sdmac->desc.callback_param);
}
@@ -1129,7 +1128,7 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
last_used = chan->cookie;
- dma_set_tx_state(txstate, sdmac->last_completed, last_used,
+ dma_set_tx_state(txstate, chan->completed_cookie, last_used,
sdmac->chn_count - sdmac->chn_real_count);
return sdmac->status;
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index 74f70aa..a27ae45 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -288,7 +288,7 @@ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
struct intel_mid_dma_lli *llitem;
void *param_txd = NULL;
- midc->completed = txd->cookie;
+ midc->chan.completed_cookie = txd->cookie;
callback_txd = txd->callback;
param_txd = txd->callback_param;
@@ -482,12 +482,11 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
- struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan);
dma_cookie_t last_used;
dma_cookie_t last_complete;
int ret;
- last_complete = midc->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -496,7 +495,7 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
midc_scan_descriptors(to_middma_device(chan->device), midc);
spin_unlock_bh(&midc->lock);
- last_complete = midc->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -886,7 +885,7 @@ static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan)
pm_runtime_put(&mid->pdev->dev);
return -EIO;
}
- midc->completed = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
spin_lock_bh(&midc->lock);
while (midc->descs_allocated < DESCS_PER_CHANNEL) {
diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h
index c83d35b..1bfa926 100644
--- a/drivers/dma/intel_mid_dma_regs.h
+++ b/drivers/dma/intel_mid_dma_regs.h
@@ -165,7 +165,6 @@ union intel_mid_dma_cfg_hi {
* @dma_base: MMIO register space DMA engine base pointer
* @ch_id: DMA channel id
* @lock: channel spinlock
- * @completed: DMA cookie
* @active_list: current active descriptors
* @queue: current queued up descriptors
* @free_list: current free descriptors
@@ -183,7 +182,6 @@ struct intel_mid_dma_chan {
void __iomem *dma_base;
int ch_id;
spinlock_t lock;
- dma_cookie_t completed;
struct list_head active_list;
struct list_head queue;
struct list_head free_list;
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index a4d6cb0..fab440a 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -603,7 +603,7 @@ static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)
*/
dump_desc_dbg(ioat, desc);
if (tx->cookie) {
- chan->completed_cookie = tx->cookie;
+ chan->common.completed_cookie = tx->cookie;
tx->cookie = 0;
ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
ioat->active -= desc->hw->tx_cnt;
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index 5216c8a..9653b6b 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -90,7 +90,6 @@ struct ioat_chan_common {
void __iomem *reg_base;
unsigned long last_completion;
spinlock_t cleanup_lock;
- dma_cookie_t completed_cookie;
unsigned long state;
#define IOAT_COMPLETION_PENDING 0
#define IOAT_COMPLETION_ACK 1
@@ -153,12 +152,11 @@ static inline enum dma_status
ioat_tx_status(struct dma_chan *c, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
- struct ioat_chan_common *chan = to_chan_common(c);
dma_cookie_t last_used;
dma_cookie_t last_complete;
last_used = c->cookie;
- last_complete = chan->completed_cookie;
+ last_complete = c->completed_cookie;
dma_set_tx_state(txstate, last_complete, last_used, 0);
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 5d65f83..d3f0aff 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -147,7 +147,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
dump_desc_dbg(ioat, desc);
if (tx->cookie) {
ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
- chan->completed_cookie = tx->cookie;
+ chan->common.completed_cookie = tx->cookie;
tx->cookie = 0;
if (tx->callback) {
tx->callback(tx->callback_param);
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index f519c93..d4afac7 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -277,7 +277,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
dump_desc_dbg(ioat, desc);
tx = &desc->txd;
if (tx->cookie) {
- chan->completed_cookie = tx->cookie;
+ chan->common.completed_cookie = tx->cookie;
ioat3_dma_unmap(ioat, desc, idx + i);
tx->cookie = 0;
if (tx->callback) {
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 04be90b..d8027c2 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -317,7 +317,7 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
}
if (cookie > 0) {
- iop_chan->completed_cookie = cookie;
+ iop_chan->common.completed_cookie = cookie;
pr_debug("\tcompleted cookie %d\n", cookie);
}
}
@@ -909,7 +909,7 @@ static enum dma_status iop_adma_status(struct dma_chan *chan,
enum dma_status ret;
last_used = chan->cookie;
- last_complete = iop_chan->completed_cookie;
+ last_complete = chan->completed_cookie;
dma_set_tx_state(txstate, last_complete, last_used, 0);
ret = dma_async_is_complete(cookie, last_complete, last_used);
if (ret == DMA_SUCCESS)
@@ -918,7 +918,7 @@ static enum dma_status iop_adma_status(struct dma_chan *chan,
iop_adma_slot_cleanup(iop_chan);
last_used = chan->cookie;
- last_complete = iop_chan->completed_cookie;
+ last_complete = chan->completed_cookie;
dma_set_tx_state(txstate, last_complete, last_used, 0);
return dma_async_is_complete(cookie, last_complete, last_used);
@@ -1650,7 +1650,7 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
/* initialize the completed cookie to be less than
* the most recently used cookie
*/
- iop_chan->completed_cookie = cookie - 1;
+ iop_chan->common.completed_cookie = cookie - 1;
iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
/* channel should not be busy */
@@ -1707,7 +1707,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
/* initialize the completed cookie to be less than
* the most recently used cookie
*/
- iop_chan->completed_cookie = cookie - 1;
+ iop_chan->common.completed_cookie = cookie - 1;
iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
/* channel should not be busy */
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 6212b16..9149ade 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1295,7 +1295,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
/* Flip the active buffer - even if update above failed */
ichan->active_buffer = !ichan->active_buffer;
if (done)
- ichan->completed = desc->txd.cookie;
+ ichan->dma_chan.completed_cookie = desc->txd.cookie;
callback = desc->txd.callback;
callback_param = desc->txd.callback_param;
@@ -1511,7 +1511,7 @@ static int idmac_alloc_chan_resources(struct dma_chan *chan)
WARN_ON(ichan->status != IPU_CHANNEL_FREE);
chan->cookie = 1;
- ichan->completed = -ENXIO;
+ chan->completed_cookie = -ENXIO;
ret = ipu_irq_map(chan->chan_id);
if (ret < 0)
@@ -1600,9 +1600,7 @@ static void idmac_free_chan_resources(struct dma_chan *chan)
static enum dma_status idmac_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *txstate)
{
- struct idmac_channel *ichan = to_idmac_chan(chan);
-
- dma_set_tx_state(txstate, ichan->completed, chan->cookie, 0);
+ dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, 0);
if (cookie != chan->cookie)
return DMA_ERROR;
return DMA_SUCCESS;
@@ -1638,11 +1636,11 @@ static int __init ipu_idmac_init(struct ipu *ipu)
ichan->status = IPU_CHANNEL_FREE;
ichan->sec_chan_en = false;
- ichan->completed = -ENXIO;
snprintf(ichan->eof_name, sizeof(ichan->eof_name), "IDMAC EOF %d", i);
dma_chan->device = &idmac->dma;
dma_chan->cookie = 1;
+ dma_chan->completed_cookie = -ENXIO;
dma_chan->chan_id = i;
list_add_tail(&dma_chan->device_node, &dma->channels);
}
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 4d6d4cf..39a5cde 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -188,7 +188,6 @@ struct mpc_dma_chan {
struct list_head completed;
struct mpc_dma_tcd *tcd;
dma_addr_t tcd_paddr;
- dma_cookie_t completed_cookie;
/* Lock for this structure */
spinlock_t lock;
@@ -365,7 +364,7 @@ static void mpc_dma_process_completed(struct mpc_dma *mdma)
/* Free descriptors */
spin_lock_irqsave(&mchan->lock, flags);
list_splice_tail_init(&list, &mchan->free);
- mchan->completed_cookie = last_cookie;
+ mchan->chan.completed_cookie = last_cookie;
spin_unlock_irqrestore(&mchan->lock, flags);
}
}
@@ -568,7 +567,7 @@ mpc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
spin_lock_irqsave(&mchan->lock, flags);
last_used = mchan->chan.cookie;
- last_complete = mchan->completed_cookie;
+ last_complete = mchan->chan.completed_cookie;
spin_unlock_irqrestore(&mchan->lock, flags);
dma_set_tx_state(txstate, last_complete, last_used, 0);
@@ -742,7 +741,7 @@ static int __devinit mpc_dma_probe(struct platform_device *op)
mchan->chan.device = dma;
mchan->chan.cookie = 1;
- mchan->completed_cookie = mchan->chan.cookie;
+ mchan->chan.completed_cookie = mchan->chan.cookie;
INIT_LIST_HEAD(&mchan->free);
INIT_LIST_HEAD(&mchan->prepared);
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index ad7d03f..c6a84da 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -435,7 +435,7 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
}
if (cookie > 0)
- mv_chan->completed_cookie = cookie;
+ mv_chan->common.completed_cookie = cookie;
}
static void
@@ -825,7 +825,7 @@ static enum dma_status mv_xor_status(struct dma_chan *chan,
enum dma_status ret;
last_used = chan->cookie;
- last_complete = mv_chan->completed_cookie;
+ last_complete = chan->completed_cookie;
dma_set_tx_state(txstate, last_complete, last_used, 0);
ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -836,7 +836,7 @@ static enum dma_status mv_xor_status(struct dma_chan *chan,
mv_xor_slot_cleanup(mv_chan);
last_used = chan->cookie;
- last_complete = mv_chan->completed_cookie;
+ last_complete = chan->completed_cookie;
dma_set_tx_state(txstate, last_complete, last_used, 0);
return dma_async_is_complete(cookie, last_complete, last_used);
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h
index da04ac2..654876b 100644
--- a/drivers/dma/mv_xor.h
+++ b/drivers/dma/mv_xor.h
@@ -78,7 +78,6 @@ struct mv_xor_device {
/**
* struct mv_xor_chan - internal representation of a XOR channel
* @pending: allows batching of hardware operations
- * @completed_cookie: identifier for the most recently completed operation
* @lock: serializes enqueue/dequeue operations to the descriptors pool
* @mmr_base: memory mapped register base
* @idx: the index of the xor channel
@@ -93,7 +92,6 @@ struct mv_xor_device {
*/
struct mv_xor_chan {
int pending;
- dma_cookie_t completed_cookie;
spinlock_t lock; /* protects the descriptor slot pool */
void __iomem *mmr_base;
unsigned int idx;
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index b06cd4c..3696e6e 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -111,7 +111,6 @@ struct mxs_dma_chan {
struct mxs_dma_ccw *ccw;
dma_addr_t ccw_phys;
int desc_count;
- dma_cookie_t last_completed;
enum dma_status status;
unsigned int flags;
#define MXS_DMA_SG_LOOP (1 << 0)
@@ -274,7 +273,7 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
stat1 &= ~(1 << channel);
if (mxs_chan->status == DMA_SUCCESS)
- mxs_chan->last_completed = mxs_chan->desc.cookie;
+ mxs_chan->chan.completed_cookie = mxs_chan->desc.cookie;
/* schedule tasklet on this channel */
tasklet_schedule(&mxs_chan->tasklet);
@@ -538,7 +537,7 @@ static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
dma_cookie_t last_used;
last_used = chan->cookie;
- dma_set_tx_state(txstate, mxs_chan->last_completed, last_used, 0);
+ dma_set_tx_state(txstate, chan->completed_cookie, last_used, 0);
return mxs_chan->status;
}
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 823f581..79a7185 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -105,7 +105,6 @@ struct pch_dma_chan {
spinlock_t lock;
- dma_cookie_t completed_cookie;
struct list_head active_list;
struct list_head queue;
struct list_head free_list;
@@ -544,7 +543,7 @@ static int pd_alloc_chan_resources(struct dma_chan *chan)
spin_lock_irq(&pd_chan->lock);
list_splice(&tmp_list, &pd_chan->free_list);
pd_chan->descs_allocated = i;
- pd_chan->completed_cookie = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
spin_unlock_irq(&pd_chan->lock);
pdc_enable_irq(chan, 1);
@@ -583,7 +582,7 @@ static enum dma_status pd_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
int ret;
spin_lock_irq(&pd_chan->lock);
- last_completed = pd_chan->completed_cookie;
+ last_completed = chan->completed_cookie;
last_used = chan->cookie;
spin_unlock_irq(&pd_chan->lock);
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index b8ec03e..bdf04f1 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -51,9 +51,6 @@ struct dma_pl330_chan {
/* DMA-Engine Channel */
struct dma_chan chan;
- /* Last completed cookie */
- dma_cookie_t completed;
-
/* List of to be xfered descriptors */
struct list_head work_list;
@@ -234,7 +231,7 @@ static void pl330_tasklet(unsigned long data)
/* Pick up ripe tomatoes */
list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
if (desc->status == DONE) {
- pch->completed = desc->txd.cookie;
+ pch->chan.completed_cookie = desc->txd.cookie;
list_move_tail(&desc->node, &list);
}
@@ -305,7 +302,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
spin_lock_irqsave(&pch->lock, flags);
- pch->completed = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
pch->cyclic = false;
pch->pl330_chid = pl330_request_channel(&pdmac->pif);
@@ -400,7 +397,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
dma_cookie_t last_done, last_used;
int ret;
- last_done = pch->completed;
+ last_done = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_done, last_used);
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index fc457a7..f878322 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -1930,7 +1930,7 @@ static void __ppc440spe_adma_slot_cleanup(struct ppc440spe_adma_chan *chan)
if (end_of_chain && slot_cnt) {
/* Should wait for ZeroSum completion */
if (cookie > 0)
- chan->completed_cookie = cookie;
+ chan->common.completed_cookie = cookie;
return;
}
@@ -1960,7 +1960,7 @@ static void __ppc440spe_adma_slot_cleanup(struct ppc440spe_adma_chan *chan)
BUG_ON(!seen_current);
if (cookie > 0) {
- chan->completed_cookie = cookie;
+ chan->common.completed_cookie = cookie;
pr_debug("\tcompleted cookie %d\n", cookie);
}
@@ -3950,7 +3950,7 @@ static enum dma_status ppc440spe_adma_tx_status(struct dma_chan *chan,
ppc440spe_chan = to_ppc440spe_adma_chan(chan);
last_used = chan->cookie;
- last_complete = ppc440spe_chan->completed_cookie;
+ last_complete = chan->completed_cookie;
dma_set_tx_state(txstate, last_complete, last_used, 0);
@@ -3961,7 +3961,7 @@ static enum dma_status ppc440spe_adma_tx_status(struct dma_chan *chan,
ppc440spe_adma_slot_cleanup(ppc440spe_chan);
last_used = chan->cookie;
- last_complete = ppc440spe_chan->completed_cookie;
+ last_complete = chan->completed_cookie;
dma_set_tx_state(txstate, last_complete, last_used, 0);
@@ -4058,7 +4058,7 @@ static void ppc440spe_chan_start_null_xor(struct ppc440spe_adma_chan *chan)
/* initialize the completed cookie to be less than
* the most recently used cookie
*/
- chan->completed_cookie = cookie - 1;
+ chan->common.completed_cookie = cookie - 1;
chan->common.cookie = sw_desc->async_tx.cookie = cookie;
/* channel should not be busy */
diff --git a/drivers/dma/ppc4xx/adma.h b/drivers/dma/ppc4xx/adma.h
index 8ada5a8..26b7a5e 100644
--- a/drivers/dma/ppc4xx/adma.h
+++ b/drivers/dma/ppc4xx/adma.h
@@ -81,7 +81,6 @@ struct ppc440spe_adma_device {
* @common: common dmaengine channel object members
* @all_slots: complete domain of slots usable by the channel
* @pending: allows batching of hardware operations
- * @completed_cookie: identifier for the most recently completed operation
* @slots_allocated: records the actual size of the descriptor slot pool
* @hw_chain_inited: h/w descriptor chain initialization flag
* @irq_tasklet: bottom half where ppc440spe_adma_slot_cleanup runs
@@ -99,7 +98,6 @@ struct ppc440spe_adma_chan {
struct list_head all_slots;
struct ppc440spe_adma_desc_slot *last_used;
int pending;
- dma_cookie_t completed_cookie;
int slots_allocated;
int hw_chain_inited;
struct tasklet_struct irq_tasklet;
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 812fd76..ae84c12 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -764,12 +764,12 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
cookie = tx->cookie;
if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
- if (sh_chan->completed_cookie != desc->cookie - 1)
+ if (sh_chan->common.completed_cookie != desc->cookie - 1)
dev_dbg(sh_chan->dev,
"Completing cookie %d, expected %d\n",
desc->cookie,
- sh_chan->completed_cookie + 1);
- sh_chan->completed_cookie = desc->cookie;
+ sh_chan->common.completed_cookie + 1);
+ sh_chan->common.completed_cookie = desc->cookie;
}
/* Call callback on the last chunk */
@@ -823,7 +823,7 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
* Terminating and the loop completed normally: forgive
* uncompleted cookies
*/
- sh_chan->completed_cookie = sh_chan->common.cookie;
+ sh_chan->common.completed_cookie = sh_chan->common.cookie;
spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
@@ -891,7 +891,7 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
sh_dmae_chan_ld_cleanup(sh_chan, false);
/* First read completed cookie to avoid a skew */
- last_complete = sh_chan->completed_cookie;
+ last_complete = chan->completed_cookie;
rmb();
last_used = chan->cookie;
BUG_ON(last_complete < 0);
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 2b55a27..0b1d2c1 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -30,7 +30,6 @@ enum dmae_pm_state {
};
struct sh_dmae_chan {
- dma_cookie_t completed_cookie; /* The maximum cookie completed */
spinlock_t desc_lock; /* Descriptor operation lock */
struct list_head ld_queue; /* Link descriptors queue */
struct list_head ld_free; /* Link descriptors free */
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 2333810..60473f0 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -59,7 +59,6 @@ struct sirfsoc_dma_chan {
struct list_head queued;
struct list_head active;
struct list_head completed;
- dma_cookie_t completed_cookie;
unsigned long happened_cyclic;
unsigned long completed_cyclic;
@@ -208,7 +207,7 @@ static void sirfsoc_dma_process_completed(struct sirfsoc_dma *sdma)
/* Free descriptors */
spin_lock_irqsave(&schan->lock, flags);
list_splice_tail_init(&list, &schan->free);
- schan->completed_cookie = last_cookie;
+ schan->chan.completed_cookie = last_cookie;
spin_unlock_irqrestore(&schan->lock, flags);
} else {
/* for cyclic channel, desc is always in active list */
@@ -419,7 +418,7 @@ sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
spin_lock_irqsave(&schan->lock, flags);
last_used = schan->chan.cookie;
- last_complete = schan->completed_cookie;
+ last_complete = schan->chan.completed_cookie;
spin_unlock_irqrestore(&schan->lock, flags);
dma_set_tx_state(txstate, last_complete, last_used, 0);
@@ -636,7 +635,7 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
schan->chan.device = dma;
schan->chan.cookie = 1;
- schan->completed_cookie = schan->chan.cookie;
+ schan->chan.completed_cookie = schan->chan.cookie;
INIT_LIST_HEAD(&schan->free);
INIT_LIST_HEAD(&schan->prepared);
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index cc5ecbc..cfca2a0 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -220,8 +220,6 @@ struct d40_base;
*
* @lock: A spinlock to protect this struct.
* @log_num: The logical number, if any of this channel.
- * @completed: Starts with 1, after first interrupt it is set to dma engine's
- * current cookie.
* @pending_tx: The number of pending transfers. Used between interrupt handler
* and tasklet.
* @busy: Set to true when transfer is ongoing on this channel.
@@ -250,8 +248,6 @@ struct d40_base;
struct d40_chan {
spinlock_t lock;
int log_num;
- /* ID of the most recent completed transfer */
- int completed;
int pending_tx;
bool busy;
struct d40_phy_res *phy_chan;
@@ -1357,7 +1353,7 @@ static void dma_tasklet(unsigned long data)
goto err;
if (!d40d->cyclic)
- d40c->completed = d40d->txd.cookie;
+ d40c->chan.completed_cookie = d40d->txd.cookie;
/*
* If terminating a channel pending_tx is set to zero.
@@ -2182,7 +2178,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
bool is_free_phy;
spin_lock_irqsave(&d40c->lock, flags);
- d40c->completed = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
/* If no dma configuration is set use default configuration (memcpy) */
if (!d40c->configured) {
@@ -2351,7 +2347,7 @@ static enum dma_status d40_tx_status(struct dma_chan *chan,
return -EINVAL;
}
- last_complete = d40c->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
if (d40_is_paused(d40c))
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index a6f9c16..a1d1559 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -84,7 +84,6 @@ struct timb_dma_chan {
especially the lists and descriptors,
from races between the tasklet and calls
from above */
- dma_cookie_t last_completed_cookie;
bool ongoing;
struct list_head active_list;
struct list_head queue;
@@ -284,7 +283,7 @@ static void __td_finish(struct timb_dma_chan *td_chan)
else
iowrite32(0, td_chan->membase + TIMBDMA_OFFS_TX_DLAR);
*/
- td_chan->last_completed_cookie = txd->cookie;
+ td_chan->chan.completed_cookie = txd->cookie;
td_chan->ongoing = false;
callback = txd->callback;
@@ -481,7 +480,7 @@ static int td_alloc_chan_resources(struct dma_chan *chan)
}
spin_lock_bh(&td_chan->lock);
- td_chan->last_completed_cookie = 1;
+ chan->completed_cookie = 1;
chan->cookie = 1;
spin_unlock_bh(&td_chan->lock);
@@ -523,7 +522,7 @@ static enum dma_status td_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
dev_dbg(chan2dev(chan), "%s: Entry\n", __func__);
- last_complete = td_chan->last_completed_cookie;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 6122c36..a917b67 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -424,7 +424,7 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
txd->cookie, desc);
- dc->completed = txd->cookie;
+ dc->chan.completed_cookie = txd->cookie;
callback = txd->callback;
param = txd->callback_param;
@@ -976,7 +976,7 @@ txx9dmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
dma_cookie_t last_complete;
int ret;
- last_complete = dc->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -985,7 +985,7 @@ txx9dmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
txx9dmac_scan_descriptors(dc);
spin_unlock_bh(&dc->lock);
- last_complete = dc->completed;
+ last_complete = chan->completed_cookie;
last_used = chan->cookie;
ret = dma_async_is_complete(cookie, last_complete, last_used);
@@ -1057,7 +1057,7 @@ static int txx9dmac_alloc_chan_resources(struct dma_chan *chan)
return -EIO;
}
- dc->completed = chan->cookie = 1;
+ chan->completed_cookie = chan->cookie = 1;
dc->ccr = TXX9_DMA_CCR_IMMCHN | TXX9_DMA_CCR_INTENE | CCR_LE;
txx9dmac_chan_set_SMPCHN(dc);
@@ -1186,7 +1186,7 @@ static int __init txx9dmac_chan_probe(struct platform_device *pdev)
dc->ddev->chan[ch] = dc;
dc->chan.device = &dc->dma;
list_add_tail(&dc->chan.device_node, &dc->chan.device->channels);
- dc->chan.cookie = dc->completed = 1;
+ dc->chan.cookie = dc->chan.completed_cookie = 1;
if (is_dmac64(dc))
dc->ch_regs = &__txx9dmac_regs(dc->ddev)->CHAN[ch];
diff --git a/drivers/dma/txx9dmac.h b/drivers/dma/txx9dmac.h
index 365d423..f5a7605 100644
--- a/drivers/dma/txx9dmac.h
+++ b/drivers/dma/txx9dmac.h
@@ -172,7 +172,6 @@ struct txx9dmac_chan {
spinlock_t lock;
/* these other elements are all protected by lock */
- dma_cookie_t completed;
struct list_head active_list;
struct list_head queue;
struct list_head free_list;
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index 033f6aa..1bb134b 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -176,7 +176,6 @@ enum pl08x_dma_chan_state {
* @runtime_addr: address for RX/TX according to the runtime config
* @runtime_direction: current direction of this channel according to
* runtime config
- * @lc: last completed transaction on this channel
* @pend_list: queued transactions pending on this channel
* @at: active transaction on this channel
* @lock: a lock for this channel data
@@ -198,7 +197,6 @@ struct pl08x_dma_chan {
u32 src_cctl;
u32 dst_cctl;
enum dma_transfer_direction runtime_direction;
- dma_cookie_t lc;
struct list_head pend_list;
struct pl08x_txd *at;
spinlock_t lock;
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 679b349..41d0f92 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -257,6 +257,7 @@ struct dma_chan_percpu {
* struct dma_chan - devices supply DMA channels, clients use them
* @device: ptr to the dma device who supplies this channel, always !%NULL
* @cookie: last cookie value returned to client
+ * @completed_cookie: last completed cookie for this channel
* @chan_id: channel ID for sysfs
* @dev: class device for sysfs
* @device_node: used to add this to the device chan list
@@ -268,6 +269,7 @@ struct dma_chan_percpu {
struct dma_chan {
struct dma_device *device;
dma_cookie_t cookie;
+ dma_cookie_t completed_cookie;
/* sysfs */
int chan_id;
--
1.7.4.4
^ permalink raw reply related
* [PATCH 3/9] dmaengine: add private header file
From: Russell King - ARM Linux @ 2012-03-05 20:15 UTC (permalink / raw)
To: Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20120305201411.GA17791@n2100.arm.linux.org.uk>
Add a local private header file to contain definitions and declarations
which should only be used by DMA engine drivers.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/amba-pl08x.c | 2 ++
drivers/dma/at_hdmac.c | 1 +
drivers/dma/coh901318.c | 1 +
drivers/dma/dmaengine.h | 10 ++++++++++
drivers/dma/dw_dmac.c | 1 +
drivers/dma/ep93xx_dma.c | 2 ++
drivers/dma/fsldma.c | 1 +
drivers/dma/imx-dma.c | 2 ++
drivers/dma/imx-sdma.c | 2 ++
drivers/dma/intel_mid_dma.c | 2 ++
drivers/dma/ioat/dma.c | 2 ++
drivers/dma/ioat/dma_v2.c | 2 ++
drivers/dma/iop-adma.c | 2 ++
drivers/dma/ipu/ipu_idmac.c | 1 +
drivers/dma/mpc512x_dma.c | 2 ++
drivers/dma/mv_xor.c | 2 ++
drivers/dma/mxs-dma.c | 2 ++
drivers/dma/pch_dma.c | 2 ++
drivers/dma/pl330.c | 2 ++
drivers/dma/ppc4xx/adma.c | 1 +
drivers/dma/shdma.c | 2 ++
drivers/dma/ste_dma40.c | 1 +
drivers/dma/timb_dma.c | 2 ++
drivers/dma/txx9dmac.c | 2 ++
24 files changed, 49 insertions(+), 0 deletions(-)
create mode 100644 drivers/dma/dmaengine.h
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 2b5121f..87475cb 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -85,6 +85,8 @@
#include <linux/slab.h>
#include <asm/hardware/pl080.h>
+#include "dmaengine.h"
+
#define DRIVER_NAME "pl08xdmac"
static struct amba_driver pl08x_amba_driver;
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 6baf5d7..ce26ba3 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -27,6 +27,7 @@
#include <linux/of_device.h>
#include "at_hdmac_regs.h"
+#include "dmaengine.h"
/*
* Glossary
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 521434b..fb0d124 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -24,6 +24,7 @@
#include <mach/coh901318.h>
#include "coh901318_lli.h"
+#include "dmaengine.h"
#define COHC_2_DEV(cohc) (&cohc->chan.dev->device)
diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
new file mode 100644
index 0000000..968570d
--- /dev/null
+++ b/drivers/dma/dmaengine.h
@@ -0,0 +1,10 @@
+/*
+ * The contents of this file are private to DMA engine drivers, and is not
+ * part of the API to be used by DMA engine users.
+ */
+#ifndef DMAENGINE_H
+#define DMAENGINE_H
+
+#include <linux/dmaengine.h>
+
+#endif
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index defe574..f10dbe1 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include "dw_dmac_regs.h"
+#include "dmaengine.h"
/*
* This supports the Synopsys "DesignWare AHB Central DMA Controller",
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index bc45787..3260198 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -28,6 +28,8 @@
#include <mach/dma.h>
+#include "dmaengine.h"
+
/* M2P registers */
#define M2P_CONTROL 0x0000
#define M2P_CONTROL_STALLINT BIT(0)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 9b5cb8a..2ebbe57 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -35,6 +35,7 @@
#include <linux/dmapool.h>
#include <linux/of_platform.h>
+#include "dmaengine.h"
#include "fsldma.h"
#define chan_dbg(chan, fmt, arg...) \
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 321fc1f..51251a6 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -30,6 +30,8 @@
#include <mach/dma-v1.h>
#include <mach/hardware.h>
+#include "dmaengine.h"
+
struct imxdma_channel {
struct imxdma_engine *imxdma;
unsigned int channel;
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index e857904..9950ec3 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -42,6 +42,8 @@
#include <mach/dma.h>
#include <mach/hardware.h>
+#include "dmaengine.h"
+
/* SDMA registers */
#define SDMA_H_C0PTR 0x000
#define SDMA_H_INTR 0x004
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index a27ae45..a907dd6 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -29,6 +29,8 @@
#include <linux/intel_mid_dma.h>
#include <linux/module.h>
+#include "dmaengine.h"
+
#define MAX_CHAN 4 /*max ch across controllers*/
#include "intel_mid_dma_regs.h"
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index fab440a..dfe411b 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -40,6 +40,8 @@
#include "registers.h"
#include "hw.h"
+#include "../dmaengine.h"
+
int ioat_pending_level = 4;
module_param(ioat_pending_level, int, 0644);
MODULE_PARM_DESC(ioat_pending_level,
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index d3f0aff..6c1e675 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -41,6 +41,8 @@
#include "registers.h"
#include "hw.h"
+#include "../dmaengine.h"
+
int ioat_ring_alloc_order = 8;
module_param(ioat_ring_alloc_order, int, 0644);
MODULE_PARM_DESC(ioat_ring_alloc_order,
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index d8027c2..650bf1e 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -36,6 +36,8 @@
#include <mach/adma.h>
+#include "dmaengine.h"
+
#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
#define to_iop_adma_device(dev) \
container_of(dev, struct iop_adma_device, common)
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 9149ade..0fcff65 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -25,6 +25,7 @@
#include <mach/ipu.h>
+#include "../dmaengine.h"
#include "ipu_intern.h"
#define FS_VF_IN_VALID 0x00000002
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 39a5cde..c56b3fe 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -44,6 +44,8 @@
#include <linux/random.h>
+#include "dmaengine.h"
+
/* Number of DMA Transfer descriptors allocated per channel */
#define MPC_DMA_DESCRIPTORS 64
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index c6a84da..ee61778 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -26,6 +26,8 @@
#include <linux/platform_device.h>
#include <linux/memory.h>
#include <plat/mv_xor.h>
+
+#include "dmaengine.h"
#include "mv_xor.h"
static void mv_xor_issue_pending(struct dma_chan *chan);
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 3696e6e..daa84ee 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -28,6 +28,8 @@
#include <mach/dma.h>
#include <mach/common.h>
+#include "dmaengine.h"
+
/*
* NOTE: The term "PIO" throughout the mxs-dma implementation means
* PIO mode of mxs apbh-dma and apbx-dma. With this working mode,
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 79a7185..2b3479d 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -25,6 +25,8 @@
#include <linux/module.h>
#include <linux/pch_dma.h>
+#include "dmaengine.h"
+
#define DRV_NAME "pch-dma"
#define DMA_CTL0_DISABLE 0x0
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index bdf04f1..d7b0af2 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -21,6 +21,8 @@
#include <linux/scatterlist.h>
#include <linux/of.h>
+#include "dmaengine.h"
+
#define NR_DEFAULT_DESC 16
enum desc_status {
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index f878322..40082ec 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -46,6 +46,7 @@
#include <asm/dcr.h>
#include <asm/dcr-regs.h>
#include "adma.h"
+#include "../dmaengine.h"
enum ppc_adma_init_code {
PPC_ADMA_INIT_OK = 0,
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index ae84c12..c291433 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -30,6 +30,8 @@
#include <linux/kdebug.h>
#include <linux/spinlock.h>
#include <linux/rculist.h>
+
+#include "dmaengine.h"
#include "shdma.h"
/* DMA descriptor control */
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index cfca2a0..156b98f 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -21,6 +21,7 @@
#include <plat/ste_dma40.h>
+#include "dmaengine.h"
#include "ste_dma40_ll.h"
#define D40_NAME "dma40"
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index a1d1559..4b61879 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -31,6 +31,8 @@
#include <linux/timb_dma.h>
+#include "dmaengine.h"
+
#define DRIVER_NAME "timb-dma"
/* Global DMA registers */
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index a917b67..db6d809 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -15,6 +15,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/scatterlist.h>
+
+#include "dmaengine.h"
#include "txx9dmac.h"
static struct txx9dmac_chan *to_txx9dmac_chan(struct dma_chan *chan)
--
1.7.4.4
^ permalink raw reply related
* [PATCH 4/9] dmaengine: consolidate assignment of DMA cookies
From: Russell King - ARM Linux @ 2012-03-05 20:16 UTC (permalink / raw)
To: Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, Barry Song, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20120305201411.GA17791@n2100.arm.linux.org.uk>
Everyone deals with assigning DMA cookies in the same way (it's part of
the API so they should be), so lets consolidate the common code into a
helper function to avoid this duplication.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/amba-pl08x.c | 9 +++------
drivers/dma/at_hdmac.c | 23 +----------------------
drivers/dma/coh901318.c | 20 +++-----------------
drivers/dma/dmaengine.h | 20 ++++++++++++++++++++
drivers/dma/dw_dmac.c | 17 +----------------
drivers/dma/ep93xx_dma.c | 9 +--------
drivers/dma/fsldma.c | 9 +--------
drivers/dma/imx-dma.c | 15 +--------------
drivers/dma/imx-sdma.c | 15 +--------------
drivers/dma/intel_mid_dma.c | 9 +--------
drivers/dma/ioat/dma.c | 7 +------
drivers/dma/ioat/dma_v2.c | 8 ++------
drivers/dma/iop-adma.c | 14 +-------------
drivers/dma/ipu/ipu_idmac.c | 9 +--------
drivers/dma/mpc512x_dma.c | 8 +-------
drivers/dma/mv_xor.c | 14 +-------------
drivers/dma/mxs-dma.c | 15 +--------------
drivers/dma/pch_dma.c | 16 +---------------
drivers/dma/pl330.c | 14 ++------------
drivers/dma/ppc4xx/adma.c | 19 +------------------
drivers/dma/shdma.c | 8 +-------
drivers/dma/sirf-dma.c | 8 +-------
drivers/dma/ste_dma40.c | 13 +++----------
drivers/dma/timb_dma.c | 7 +------
drivers/dma/txx9dmac.c | 17 +----------------
25 files changed, 52 insertions(+), 271 deletions(-)
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 87475cb..5996386 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -921,13 +921,10 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
struct pl08x_dma_chan *plchan = to_pl08x_chan(tx->chan);
struct pl08x_txd *txd = to_pl08x_txd(tx);
unsigned long flags;
+ dma_cookie_t cookie;
spin_lock_irqsave(&plchan->lock, flags);
-
- plchan->chan.cookie += 1;
- if (plchan->chan.cookie < 0)
- plchan->chan.cookie = 1;
- tx->cookie = plchan->chan.cookie;
+ cookie = dma_cookie_assign(tx);
/* Put this onto the pending list */
list_add_tail(&txd->node, &plchan->pend_list);
@@ -947,7 +944,7 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
spin_unlock_irqrestore(&plchan->lock, flags);
- return tx->cookie;
+ return cookie;
}
static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt(
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index ce26ba3..df47e7d 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -193,27 +193,6 @@ static void atc_desc_chain(struct at_desc **first, struct at_desc **prev,
}
/**
- * atc_assign_cookie - compute and assign new cookie
- * @atchan: channel we work on
- * @desc: descriptor to assign cookie for
- *
- * Called with atchan->lock held and bh disabled
- */
-static dma_cookie_t
-atc_assign_cookie(struct at_dma_chan *atchan, struct at_desc *desc)
-{
- dma_cookie_t cookie = atchan->chan_common.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- atchan->chan_common.cookie = cookie;
- desc->txd.cookie = cookie;
-
- return cookie;
-}
-
-/**
* atc_dostart - starts the DMA engine for real
* @atchan: the channel we want to start
* @first: first descriptor in the list we want to begin with
@@ -548,7 +527,7 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
unsigned long flags;
spin_lock_irqsave(&atchan->lock, flags);
- cookie = atc_assign_cookie(atchan, desc);
+ cookie = dma_cookie_assign(tx);
if (list_empty(&atchan->active_list)) {
dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index fb0d124..843a1a3 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -318,20 +318,6 @@ static int coh901318_prep_linked_list(struct coh901318_chan *cohc,
return 0;
}
-static dma_cookie_t
-coh901318_assign_cookie(struct coh901318_chan *cohc,
- struct coh901318_desc *cohd)
-{
- dma_cookie_t cookie = cohc->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- cohc->chan.cookie = cookie;
- cohd->desc.cookie = cookie;
-
- return cookie;
-}
static struct coh901318_desc *
coh901318_desc_get(struct coh901318_chan *cohc)
@@ -966,16 +952,16 @@ coh901318_tx_submit(struct dma_async_tx_descriptor *tx)
desc);
struct coh901318_chan *cohc = to_coh901318_chan(tx->chan);
unsigned long flags;
+ dma_cookie_t cookie;
spin_lock_irqsave(&cohc->lock, flags);
-
- tx->cookie = coh901318_assign_cookie(cohc, cohd);
+ cookie = dma_cookie_assign(tx);
coh901318_desc_queue(cohc, cohd);
spin_unlock_irqrestore(&cohc->lock, flags);
- return tx->cookie;
+ return cookie;
}
static struct dma_async_tx_descriptor *
diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
index 968570d..7692c86 100644
--- a/drivers/dma/dmaengine.h
+++ b/drivers/dma/dmaengine.h
@@ -7,4 +7,24 @@
#include <linux/dmaengine.h>
+/**
+ * dma_cookie_assign - assign a DMA engine cookie to the descriptor
+ * @tx: descriptor needing cookie
+ *
+ * Assign a unique non-zero per-channel cookie to the descriptor.
+ * Note: caller is expected to hold a lock to prevent concurrency.
+ */
+static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx)
+{
+ struct dma_chan *chan = tx->chan;
+ dma_cookie_t cookie;
+
+ cookie = chan->cookie + 1;
+ if (cookie < DMA_MIN_COOKIE)
+ cookie = DMA_MIN_COOKIE;
+ tx->cookie = chan->cookie = cookie;
+
+ return cookie;
+}
+
#endif
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index f10dbe1..5ee9498 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -152,21 +152,6 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
}
}
-/* Called with dwc->lock held and bh disabled */
-static dma_cookie_t
-dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc)
-{
- dma_cookie_t cookie = dwc->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- dwc->chan.cookie = cookie;
- desc->txd.cookie = cookie;
-
- return cookie;
-}
-
static void dwc_initialize(struct dw_dma_chan *dwc)
{
struct dw_dma *dw = to_dw_dma(dwc->chan.device);
@@ -616,7 +601,7 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
unsigned long flags;
spin_lock_irqsave(&dwc->lock, flags);
- cookie = dwc_assign_cookie(dwc, desc);
+ cookie = dma_cookie_assign(tx);
/*
* REVISIT: We should attempt to chain as many descriptors as
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 3260198..e5aaae8 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -783,17 +783,10 @@ static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
unsigned long flags;
spin_lock_irqsave(&edmac->lock, flags);
-
- cookie = edmac->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
+ cookie = dma_cookie_assign(tx);
desc = container_of(tx, struct ep93xx_dma_desc, txd);
- edmac->chan.cookie = cookie;
- desc->txd.cookie = cookie;
-
/*
* If nothing is currently prosessed, we push this descriptor
* directly to the hardware. Otherwise we put the descriptor
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 2ebbe57..04b4347 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -414,17 +414,10 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
* assign cookies to all of the software descriptors
* that make up this transaction
*/
- cookie = chan->common.cookie;
list_for_each_entry(child, &desc->tx_list, node) {
- cookie++;
- if (cookie < DMA_MIN_COOKIE)
- cookie = DMA_MIN_COOKIE;
-
- child->async_tx.cookie = cookie;
+ cookie = dma_cookie_assign(&child->async_tx);
}
- chan->common.cookie = cookie;
-
/* put this transaction onto the tail of the pending queue */
append_ld_queue(chan, desc);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 51251a6..42154b6 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -165,19 +165,6 @@ static enum dma_status imxdma_tx_status(struct dma_chan *chan,
return ret;
}
-static dma_cookie_t imxdma_assign_cookie(struct imxdma_channel *imxdma)
-{
- dma_cookie_t cookie = imxdma->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- imxdma->chan.cookie = cookie;
- imxdma->desc.cookie = cookie;
-
- return cookie;
-}
-
static dma_cookie_t imxdma_tx_submit(struct dma_async_tx_descriptor *tx)
{
struct imxdma_channel *imxdmac = to_imxdma_chan(tx->chan);
@@ -185,7 +172,7 @@ static dma_cookie_t imxdma_tx_submit(struct dma_async_tx_descriptor *tx)
spin_lock_irq(&imxdmac->lock);
- cookie = imxdma_assign_cookie(imxdmac);
+ cookie = dma_cookie_assign(tx);
imx_dma_enable(imxdmac->imxdma_channel);
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 9950ec3..4e4f40e 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -817,19 +817,6 @@ static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
__raw_writel(1 << channel, sdma->regs + SDMA_H_START);
}
-static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdmac)
-{
- dma_cookie_t cookie = sdmac->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- sdmac->chan.cookie = cookie;
- sdmac->desc.cookie = cookie;
-
- return cookie;
-}
-
static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
{
return container_of(chan, struct sdma_channel, chan);
@@ -844,7 +831,7 @@ static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
spin_lock_irqsave(&sdmac->lock, flags);
- cookie = sdma_assign_cookie(sdmac);
+ cookie = dma_cookie_assign(tx);
sdma_enable_channel(sdma, sdmac->channel);
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index a907dd6..dfe4396 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -436,14 +436,7 @@ static dma_cookie_t intel_mid_dma_tx_submit(struct dma_async_tx_descriptor *tx)
dma_cookie_t cookie;
spin_lock_bh(&midc->lock);
- cookie = midc->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- midc->chan.cookie = cookie;
- desc->txd.cookie = cookie;
-
+ cookie = dma_cookie_assign(tx);
if (list_empty(&midc->active_list))
list_add_tail(&desc->desc_node, &midc->active_list);
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index dfe411b..5c06117 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -237,12 +237,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
spin_lock_bh(&ioat->desc_lock);
/* cookie incr and addition to used_list must be atomic */
- cookie = c->cookie;
- cookie++;
- if (cookie < 0)
- cookie = 1;
- c->cookie = cookie;
- tx->cookie = cookie;
+ cookie = dma_cookie_assign(tx);
dev_dbg(to_dev(&ioat->base), "%s: cookie: %d\n", __func__, cookie);
/* write address into NextDescriptor field of last desc in chain */
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 6c1e675..17ecacb 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -400,13 +400,9 @@ static dma_cookie_t ioat2_tx_submit_unlock(struct dma_async_tx_descriptor *tx)
struct dma_chan *c = tx->chan;
struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
struct ioat_chan_common *chan = &ioat->base;
- dma_cookie_t cookie = c->cookie;
+ dma_cookie_t cookie;
- cookie++;
- if (cookie < 0)
- cookie = 1;
- tx->cookie = cookie;
- c->cookie = cookie;
+ cookie = dma_cookie_assign(tx);
dev_dbg(to_dev(&ioat->base), "%s: cookie: %d\n", __func__, cookie);
if (!test_and_set_bit(IOAT_COMPLETION_PENDING, &chan->state))
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 650bf1e..f2392d5 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -440,18 +440,6 @@ iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
return NULL;
}
-static dma_cookie_t
-iop_desc_assign_cookie(struct iop_adma_chan *iop_chan,
- struct iop_adma_desc_slot *desc)
-{
- dma_cookie_t cookie = iop_chan->common.cookie;
- cookie++;
- if (cookie < 0)
- cookie = 1;
- iop_chan->common.cookie = desc->async_tx.cookie = cookie;
- return cookie;
-}
-
static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
{
dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
@@ -479,7 +467,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
slots_per_op = grp_start->slots_per_op;
spin_lock_bh(&iop_chan->lock);
- cookie = iop_desc_assign_cookie(iop_chan, sw_desc);
+ cookie = dma_cookie_assign(tx);
old_chain_tail = list_entry(iop_chan->chain.prev,
struct iop_adma_desc_slot, chain_node);
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 0fcff65..d4620c5 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -867,14 +867,7 @@ static dma_cookie_t idmac_tx_submit(struct dma_async_tx_descriptor *tx)
dev_dbg(dev, "Submitting sg %p\n", &desc->sg[0]);
- cookie = ichan->dma_chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- /* from dmaengine.h: "last cookie value returned to client" */
- ichan->dma_chan.cookie = cookie;
- tx->cookie = cookie;
+ cookie = dma_cookie_assign(tx);
/* ipu->lock can be taken under ichan->lock, but not v.v. */
spin_lock_irqsave(&ichan->lock, flags);
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index c56b3fe..0253d5a 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -439,13 +439,7 @@ static dma_cookie_t mpc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
mpc_dma_execute(mchan);
/* Update cookie */
- cookie = mchan->chan.cookie + 1;
- if (cookie <= 0)
- cookie = 1;
-
- mchan->chan.cookie = cookie;
- mdesc->desc.cookie = cookie;
-
+ cookie = dma_cookie_assign(txd);
spin_unlock_irqrestore(&mchan->lock, flags);
return cookie;
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index ee61778..d9810ce 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -536,18 +536,6 @@ mv_xor_alloc_slots(struct mv_xor_chan *mv_chan, int num_slots,
return NULL;
}
-static dma_cookie_t
-mv_desc_assign_cookie(struct mv_xor_chan *mv_chan,
- struct mv_xor_desc_slot *desc)
-{
- dma_cookie_t cookie = mv_chan->common.cookie;
-
- if (++cookie < 0)
- cookie = 1;
- mv_chan->common.cookie = desc->async_tx.cookie = cookie;
- return cookie;
-}
-
/************************ DMA engine API functions ****************************/
static dma_cookie_t
mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
@@ -565,7 +553,7 @@ mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
grp_start = sw_desc->group_head;
spin_lock_bh(&mv_chan->lock);
- cookie = mv_desc_assign_cookie(mv_chan, sw_desc);
+ cookie = dma_cookie_assign(tx);
if (list_empty(&mv_chan->chain))
list_splice_init(&sw_desc->tx_list, &mv_chan->chain);
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index daa84ee..4d3b6ff 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -194,19 +194,6 @@ static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan)
mxs_chan->status = DMA_IN_PROGRESS;
}
-static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan)
-{
- dma_cookie_t cookie = mxs_chan->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- mxs_chan->chan.cookie = cookie;
- mxs_chan->desc.cookie = cookie;
-
- return cookie;
-}
-
static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
{
return container_of(chan, struct mxs_dma_chan, chan);
@@ -218,7 +205,7 @@ static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
mxs_dma_enable_chan(mxs_chan);
- return mxs_dma_assign_cookie(mxs_chan);
+ return dma_cookie_assign(tx);
}
static void mxs_dma_tasklet(unsigned long data)
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 2b3479d..5218e48 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -417,20 +417,6 @@ static void pdc_advance_work(struct pch_dma_chan *pd_chan)
}
}
-static dma_cookie_t pdc_assign_cookie(struct pch_dma_chan *pd_chan,
- struct pch_dma_desc *desc)
-{
- dma_cookie_t cookie = pd_chan->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- pd_chan->chan.cookie = cookie;
- desc->txd.cookie = cookie;
-
- return cookie;
-}
-
static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd)
{
struct pch_dma_desc *desc = to_pd_desc(txd);
@@ -438,7 +424,7 @@ static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd)
dma_cookie_t cookie;
spin_lock(&pd_chan->lock);
- cookie = pdc_assign_cookie(pd_chan, desc);
+ cookie = dma_cookie_assign(txd);
if (list_empty(&pd_chan->active_list)) {
list_add_tail(&desc->desc_node, &pd_chan->active_list);
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index d7b0af2..ec9638b 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -429,26 +429,16 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
spin_lock_irqsave(&pch->lock, flags);
/* Assign cookies to all nodes */
- cookie = tx->chan->cookie;
-
while (!list_empty(&last->node)) {
desc = list_entry(last->node.next, struct dma_pl330_desc, node);
- if (++cookie < 0)
- cookie = 1;
- desc->txd.cookie = cookie;
+ dma_cookie_assign(&desc->txd);
list_move_tail(&desc->node, &pch->work_list);
}
- if (++cookie < 0)
- cookie = 1;
- last->txd.cookie = cookie;
-
+ cookie = dma_cookie_assign(&last->txd);
list_add_tail(&last->node, &pch->work_list);
-
- tx->chan->cookie = cookie;
-
spin_unlock_irqrestore(&pch->lock, flags);
return cookie;
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 40082ec..12e94dd 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -2151,22 +2151,6 @@ static int ppc440spe_adma_alloc_chan_resources(struct dma_chan *chan)
}
/**
- * ppc440spe_desc_assign_cookie - assign a cookie
- */
-static dma_cookie_t ppc440spe_desc_assign_cookie(
- struct ppc440spe_adma_chan *chan,
- struct ppc440spe_adma_desc_slot *desc)
-{
- dma_cookie_t cookie = chan->common.cookie;
-
- cookie++;
- if (cookie < 0)
- cookie = 1;
- chan->common.cookie = desc->async_tx.cookie = cookie;
- return cookie;
-}
-
-/**
* ppc440spe_rxor_set_region_data -
*/
static void ppc440spe_rxor_set_region(struct ppc440spe_adma_desc_slot *desc,
@@ -2236,8 +2220,7 @@ static dma_cookie_t ppc440spe_adma_tx_submit(struct dma_async_tx_descriptor *tx)
slots_per_op = group_start->slots_per_op;
spin_lock_bh(&chan->lock);
-
- cookie = ppc440spe_desc_assign_cookie(chan, sw_desc);
+ cookie = dma_cookie_assign(tx);
if (unlikely(list_empty(&chan->chain))) {
/* first peer */
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index c291433..96d0a4f 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -298,13 +298,7 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
else
power_up = false;
- cookie = sh_chan->common.cookie;
- cookie++;
- if (cookie < 0)
- cookie = 1;
-
- sh_chan->common.cookie = cookie;
- tx->cookie = cookie;
+ cookie = dma_cookie_assign(tx);
/* Mark all chunks of this descriptor as submitted, move to the queue */
list_for_each_entry_safe(chunk, c, desc->node.prev, node) {
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 60473f0..7bb154a 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -257,13 +257,7 @@ static dma_cookie_t sirfsoc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
/* Move descriptor to queue */
list_move_tail(&sdesc->node, &schan->queued);
- /* Update cookie */
- cookie = schan->chan.cookie + 1;
- if (cookie <= 0)
- cookie = 1;
-
- schan->chan.cookie = cookie;
- sdesc->desc.cookie = cookie;
+ cookie = dma_cookie_assign(txd);
spin_unlock_irqrestore(&schan->lock, flags);
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 156b98f..23e2edc 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1220,21 +1220,14 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
chan);
struct d40_desc *d40d = container_of(tx, struct d40_desc, txd);
unsigned long flags;
+ dma_cookie_t cookie;
spin_lock_irqsave(&d40c->lock, flags);
-
- d40c->chan.cookie++;
-
- if (d40c->chan.cookie < 0)
- d40c->chan.cookie = 1;
-
- d40d->txd.cookie = d40c->chan.cookie;
-
+ cookie = dma_cookie_assign(tx);
d40_desc_queue(d40c, d40d);
-
spin_unlock_irqrestore(&d40c->lock, flags);
- return tx->cookie;
+ return cookie;
}
static int d40_start(struct d40_chan *d40c)
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 4b61879..b6e83fc 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -350,12 +350,7 @@ static dma_cookie_t td_tx_submit(struct dma_async_tx_descriptor *txd)
dma_cookie_t cookie;
spin_lock_bh(&td_chan->lock);
-
- cookie = txd->chan->cookie;
- if (++cookie < 0)
- cookie = 1;
- txd->chan->cookie = cookie;
- txd->cookie = cookie;
+ cookie = dma_cookie_assign(txd);
if (list_empty(&td_chan->active_list)) {
dev_dbg(chan2dev(txd->chan), "%s: started %u\n", __func__,
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index db6d809..66f8fca 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -281,21 +281,6 @@ static void txx9dmac_desc_put(struct txx9dmac_chan *dc,
}
}
-/* Called with dc->lock held and bh disabled */
-static dma_cookie_t
-txx9dmac_assign_cookie(struct txx9dmac_chan *dc, struct txx9dmac_desc *desc)
-{
- dma_cookie_t cookie = dc->chan.cookie;
-
- if (++cookie < 0)
- cookie = 1;
-
- dc->chan.cookie = cookie;
- desc->txd.cookie = cookie;
-
- return cookie;
-}
-
/*----------------------------------------------------------------------*/
static void txx9dmac_dump_regs(struct txx9dmac_chan *dc)
@@ -740,7 +725,7 @@ static dma_cookie_t txx9dmac_tx_submit(struct dma_async_tx_descriptor *tx)
dma_cookie_t cookie;
spin_lock_bh(&dc->lock);
- cookie = txx9dmac_assign_cookie(dc, desc);
+ cookie = dma_cookie_assign(tx);
dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u %p\n",
desc->txd.cookie, desc);
--
1.7.4.4
^ permalink raw reply related
* [PATCH 5/9] dmaengine: provide a common function for completing a dma descriptor
From: Russell King - ARM Linux @ 2012-03-05 20:16 UTC (permalink / raw)
To: Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20120305201411.GA17791@n2100.arm.linux.org.uk>
Provide a common function to do the cookie mechanics for completing
a DMA descriptor.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/amba-pl08x.c | 2 +-
drivers/dma/at_hdmac.c | 2 +-
drivers/dma/coh901318.c | 2 +-
drivers/dma/dmaengine.h | 18 ++++++++++++++++++
drivers/dma/dw_dmac.c | 2 +-
drivers/dma/ep93xx_dma.c | 2 +-
drivers/dma/fsldma.c | 2 +-
drivers/dma/imx-dma.c | 2 +-
drivers/dma/imx-sdma.c | 2 +-
drivers/dma/intel_mid_dma.c | 2 +-
drivers/dma/ioat/dma.c | 3 +--
drivers/dma/ioat/dma_v2.c | 3 +--
drivers/dma/ioat/dma_v3.c | 3 +--
drivers/dma/ipu/ipu_idmac.c | 2 +-
drivers/dma/mxs-dma.c | 2 +-
drivers/dma/pl330.c | 2 +-
drivers/dma/ste_dma40.c | 2 +-
drivers/dma/timb_dma.c | 2 +-
drivers/dma/txx9dmac.c | 2 +-
19 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 5996386..f0888c1 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1540,7 +1540,7 @@ static void pl08x_tasklet(unsigned long data)
if (txd) {
/* Update last completed */
- plchan->chan.completed_cookie = txd->tx.cookie;
+ dma_cookie_complete(&txd->tx);
}
/* If a new descriptor is queued, set it up plchan->at is NULL here */
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index df47e7d..b282630 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -249,7 +249,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
dev_vdbg(chan2dev(&atchan->chan_common),
"descriptor %u complete\n", txd->cookie);
- atchan->chan_common.completed_cookie = txd->cookie;
+ dma_cookie_complete(txd);
/* move children to free_list */
list_splice_init(&desc->tx_list, &atchan->free_list);
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 843a1a3..24837d7 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -691,7 +691,7 @@ static void dma_tasklet(unsigned long data)
callback_param = cohd_fin->desc.callback_param;
/* sign this job as completed on the channel */
- cohc->chan.completed_cookie = cohd_fin->desc.cookie;
+ dma_cookie_complete(&cohd_fin->desc);
/* release the lli allocation and remove the descriptor */
coh901318_lli_free(&cohc->base->pool, &cohd_fin->lli);
diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
index 7692c86..47e0997 100644
--- a/drivers/dma/dmaengine.h
+++ b/drivers/dma/dmaengine.h
@@ -5,6 +5,7 @@
#ifndef DMAENGINE_H
#define DMAENGINE_H
+#include <linux/bug.h>
#include <linux/dmaengine.h>
/**
@@ -27,4 +28,21 @@ static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx)
return cookie;
}
+/**
+ * dma_cookie_complete - complete a descriptor
+ * @tx: descriptor to complete
+ *
+ * Mark this descriptor complete by updating the channels completed
+ * cookie marker. Zero the descriptors cookie to prevent accidental
+ * repeated completions.
+ *
+ * Note: caller is expected to hold a lock to prevent concurrency.
+ */
+static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx)
+{
+ BUG_ON(tx->cookie < DMA_MIN_COOKIE);
+ tx->chan->completed_cookie = tx->cookie;
+ tx->cookie = 0;
+}
+
#endif
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 5ee9498..a190c88 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -231,7 +231,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc,
dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);
spin_lock_irqsave(&dwc->lock, flags);
- dwc->chan.completed_cookie = txd->cookie;
+ dma_cookie_complete(txd);
if (callback_required) {
callback = txd->callback;
param = txd->callback_param;
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index e5aaae8..1c56f75 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -703,7 +703,7 @@ static void ep93xx_dma_tasklet(unsigned long data)
desc = ep93xx_dma_get_active(edmac);
if (desc) {
if (desc->complete) {
- edmac->chan.completed_cookie = desc->txd.cookie;
+ dma_cookie_complete(&desc->txd);
list_splice_init(&edmac->active, &list);
}
callback = desc->txd.callback;
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 04b4347..f36e8b1 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1081,8 +1081,8 @@ static void dma_do_tasklet(unsigned long data)
desc = to_fsl_desc(chan->ld_running.prev);
cookie = desc->async_tx.cookie;
+ dma_cookie_complete(&desc->async_tx);
- chan->common.completed_cookie = cookie;
chan_dbg(chan, "completed_cookie=%d\n", cookie);
}
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 42154b6..f1226ad 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -66,7 +66,7 @@ static void imxdma_handle(struct imxdma_channel *imxdmac)
{
if (imxdmac->desc.callback)
imxdmac->desc.callback(imxdmac->desc.callback_param);
- imxdmac->chan.completed_cookie = imxdmac->desc.cookie;
+ dma_cookie_complete(&imxdmac->desc);
}
static void imxdma_irq_handler(int channel, void *data)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 4e4f40e..4406be2 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -524,7 +524,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
else
sdmac->status = DMA_SUCCESS;
- sdmac->chan.completed_cookie = sdmac->desc.cookie;
+ dma_cookie_complete(&sdmac->desc);
if (sdmac->desc.callback)
sdmac->desc.callback(sdmac->desc.callback_param);
}
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index dfe4396..340509e 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -290,7 +290,7 @@ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
struct intel_mid_dma_lli *llitem;
void *param_txd = NULL;
- midc->chan.completed_cookie = txd->cookie;
+ dma_cookie_complete(txd);
callback_txd = txd->callback;
param_txd = txd->callback_param;
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 5c06117..b0517c8 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -600,8 +600,7 @@ static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)
*/
dump_desc_dbg(ioat, desc);
if (tx->cookie) {
- chan->common.completed_cookie = tx->cookie;
- tx->cookie = 0;
+ dma_cookie_complete(tx);
ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
ioat->active -= desc->hw->tx_cnt;
if (tx->callback) {
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 17ecacb..e8e110f 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -149,8 +149,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
dump_desc_dbg(ioat, desc);
if (tx->cookie) {
ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
- chan->common.completed_cookie = tx->cookie;
- tx->cookie = 0;
+ dma_cookie_complete(tx);
if (tx->callback) {
tx->callback(tx->callback_param);
tx->callback = NULL;
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index d4afac7..1bda46c 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -277,9 +277,8 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
dump_desc_dbg(ioat, desc);
tx = &desc->txd;
if (tx->cookie) {
- chan->common.completed_cookie = tx->cookie;
+ dma_cookie_complete(tx);
ioat3_dma_unmap(ioat, desc, idx + i);
- tx->cookie = 0;
if (tx->callback) {
tx->callback(tx->callback_param);
tx->callback = NULL;
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index d4620c5..bff9250 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1289,7 +1289,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
/* Flip the active buffer - even if update above failed */
ichan->active_buffer = !ichan->active_buffer;
if (done)
- ichan->dma_chan.completed_cookie = desc->txd.cookie;
+ dma_cookie_complete(&desc->txd);
callback = desc->txd.callback;
callback_param = desc->txd.callback_param;
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 4d3b6ff..5f3492e 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -262,7 +262,7 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
stat1 &= ~(1 << channel);
if (mxs_chan->status == DMA_SUCCESS)
- mxs_chan->chan.completed_cookie = mxs_chan->desc.cookie;
+ dma_cookie_complete(&mxs_chan->desc);
/* schedule tasklet on this channel */
tasklet_schedule(&mxs_chan->tasklet);
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index ec9638b..76871b8 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -233,7 +233,7 @@ static void pl330_tasklet(unsigned long data)
/* Pick up ripe tomatoes */
list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
if (desc->status == DONE) {
- pch->chan.completed_cookie = desc->txd.cookie;
+ dma_cookie_complete(&desc->txd);
list_move_tail(&desc->node, &list);
}
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 23e2edc..c246375 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1347,7 +1347,7 @@ static void dma_tasklet(unsigned long data)
goto err;
if (!d40d->cyclic)
- d40c->chan.completed_cookie = d40d->txd.cookie;
+ dma_cookie_complete(&d40d->txd);
/*
* If terminating a channel pending_tx is set to zero.
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index b6e83fc..1845ac9 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -285,7 +285,7 @@ static void __td_finish(struct timb_dma_chan *td_chan)
else
iowrite32(0, td_chan->membase + TIMBDMA_OFFS_TX_DLAR);
*/
- td_chan->chan.completed_cookie = txd->cookie;
+ dma_cookie_complete(txd);
td_chan->ongoing = false;
callback = txd->callback;
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 66f8fca..8a5225b 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -411,7 +411,7 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
txd->cookie, desc);
- dc->chan.completed_cookie = txd->cookie;
+ dma_cookie_complete(txd);
callback = txd->callback;
param = txd->callback_param;
--
1.7.4.4
^ permalink raw reply related
* Re: [PATCH 0/9] DMA engine cookie handling cleanups
From: Linus Walleij @ 2012-03-05 20:50 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Vinod Koul, Zhang Wei, Barry Song, Dan Williams, linuxppc-dev,
linux-arm-kernel
In-Reply-To: <20120305201411.GA17791@n2100.arm.linux.org.uk>
On Mon, Mar 5, 2012 at 9:14 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> This patch series cleans up the handling of cookies in DMA engine drivers.
> This is done by providing a set of inline library functions for common
> tasks:
Overall this looks good, but I have a problem:
patch [1/9] does not appear in any subscribed accounts (it may be on
my @stericsson.com address, will check tomorrow)
One I get hold of an ungmangled copy I can test the series on
ux500 and U300.
Is it just stuck in moderation because of size or something like that?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] rapidio/tsi721: fix bug in inbound doorbell handler
From: Alexandre Bounine @ 2012-03-05 20:33 UTC (permalink / raw)
To: akpm, linux-kernel, linuxppc-dev; +Cc: Alexandre Bounine, Chul Kim
Fixes queue wrapping bug in Inbound Doorbell handling routine.
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Chul Kim <chul.kim@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
---
This patch is applicable to kernel version 3.2 and after.
drivers/rapidio/devices/tsi721.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index babbede..c746e26 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -406,13 +406,14 @@ static void tsi721_db_dpc(struct work_struct *work)
*/
mport = priv->mport;
- wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE));
- rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
+ wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE;
+ rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE)) % IDB_QSIZE;
while (wr_ptr != rd_ptr) {
idb_entry = (u64 *)(priv->idb_base +
(TSI721_IDB_ENTRY_SIZE * rd_ptr));
rd_ptr++;
+ rd_ptr %= IDB_QSIZE;
idb.msg = *idb_entry;
*idb_entry = 0;
--
1.7.8.4
^ permalink raw reply related
* [PATCH 9/9] dmaengine: ensure all DMA engine drivers initialize their cookies
From: Russell King - ARM Linux @ 2012-03-05 20:17 UTC (permalink / raw)
To: Dan Williams, Vinod Koul; +Cc: Zhang Wei, Stephen Warren, linuxppc-dev
In-Reply-To: <20120305201411.GA17791@n2100.arm.linux.org.uk>
Ensure all DMA engine drivers initialize their cookies in the same way,
so that they all behave in a similar fashion. This means their first
issued cookie will be 2 rather than 1, and will increment to INT_MAX
before returning 1 and starting over.
In connection with this, Dan Williams said:
> Russell King wrote:
> > Secondly, some DMA engine drivers initialize the dma_chan cookie to 0,
> > others to 1. Is there a reason for this, or are these all buggy?
>
> I know that ioat and iop-adma expect 0 to mean "I have cleaned up this
> descriptor and it is idle", and would break if zero was an in-flight
> cookie value. The reserved usage of zero is an driver internal
> concern, but I have no problem formalizing it as a reserved value.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/fsldma.c | 1 +
drivers/dma/imx-dma.c | 1 +
drivers/dma/imx-sdma.c | 1 +
drivers/dma/ioat/dma.c | 1 +
drivers/dma/iop-adma.c | 1 +
drivers/dma/mv_xor.c | 1 +
drivers/dma/mxs-dma.c | 1 +
drivers/dma/ppc4xx/adma.c | 1 +
drivers/dma/shdma.c | 1 +
9 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 2f6c806..7d7384b 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1292,6 +1292,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
chan->idle = true;
chan->common.device = &fdev->common;
+ dma_cookie_init(&chan->common);
/* find the IRQ line, if it exists in the device tree */
chan->irq = irq_of_parse_and_map(node, 0);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index ba317e6..4e14f51 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -348,6 +348,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
spin_lock_init(&imxdmac->lock);
imxdmac->chan.device = &imxdma->dma_device;
+ dma_cookie_init(&imxdmac->chan);
imxdmac->channel = i;
/* Add the channel to the DMAC list */
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 4406be2..0be36a4 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1356,6 +1356,7 @@ static int __init sdma_probe(struct platform_device *pdev)
spin_lock_init(&sdmac->lock);
sdmac->chan.device = &sdma->dma_device;
+ dma_cookie_init(&sdmac->chan);
sdmac->channel = i;
/*
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 97e100c..31493d8 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -109,6 +109,7 @@ void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *c
chan->reg_base = device->reg_base + (0x80 * (idx + 1));
spin_lock_init(&chan->cleanup_lock);
chan->common.device = dma;
+ dma_cookie_init(&chan->common);
list_add_tail(&chan->common.device_node, &dma->channels);
device->idx[idx] = chan;
init_timer(&chan->timer);
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 4370b10..1f3a703 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -1545,6 +1545,7 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&iop_chan->chain);
INIT_LIST_HEAD(&iop_chan->all_slots);
iop_chan->common.device = dma_dev;
+ dma_cookie_init(&iop_chan->common);
list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 486353e..fa5d55f 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1193,6 +1193,7 @@ static int __devinit mv_xor_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&mv_chan->completed_slots);
INIT_LIST_HEAD(&mv_chan->all_slots);
mv_chan->common.device = dma_dev;
+ dma_cookie_init(&mv_chan->common);
list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 5f3492e..a2267f9 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -618,6 +618,7 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
mxs_chan->mxs_dma = mxs_dma;
mxs_chan->chan.device = &mxs_dma->dma_device;
+ dma_cookie_init(&mxs_chan->chan);
tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet,
(unsigned long) mxs_chan);
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 9752062..ced9882 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4497,6 +4497,7 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
INIT_LIST_HEAD(&chan->all_slots);
chan->device = adev;
chan->common.device = &adev->common;
+ dma_cookie_init(&chan->common);
list_add_tail(&chan->common.device_node, &adev->common.channels);
tasklet_init(&chan->irq_tasklet, ppc440spe_adma_tasklet,
(unsigned long)chan);
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 50510ef..5c40886 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -1089,6 +1089,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
/* reference struct dma_device */
new_sh_chan->common.device = &shdev->common;
+ dma_cookie_init(&new_sh_chan->common);
new_sh_chan->dev = shdev->common.dev;
new_sh_chan->id = id;
--
1.7.4.4
^ permalink raw reply related
* RE: [PATCH] rapidio/tsi721: fix bug in inbound doorbell handler
From: Bounine, Alexandre @ 2012-03-05 20:53 UTC (permalink / raw)
To: Andrew Morton
Cc: Kim, Chul, linuxppc-dev@lists.ozlabs.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20120305123714.0750129e.akpm@linux-foundation.org>
On Mon, March 05, 2012 3:37 PM Andrew Morton wrote:
> Alexandre Bounine <alexandre.bounine@idt.com> wrote:
>=20
> > Fixes queue wrapping bug in Inbound Doorbell handling routine.
>=20
> The changelog doesn't describe the user-visible impact of the bug.
> Please always include this so that people know whether to backport the
> fix into their kernels, and so they can determine whether the patch
> will fix a problem which they are observing.
This patch fixes the bug that causes kernel panic when number of received
doorbells is larger than number of entries in the inbound doorbell
queue (current default value =3D 512).
Another possible indication for this bug is large number of spurious
doorbells reported by tsi721 driver after reaching the queue size maximum.
^ permalink raw reply
* Re: [PATCH 0/9] DMA engine cookie handling cleanups
From: Russell King - ARM Linux @ 2012-03-05 20:58 UTC (permalink / raw)
To: Linus Walleij
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Vinod Koul, Zhang Wei, Barry Song, Dan Williams, linuxppc-dev,
linux-arm-kernel
In-Reply-To: <CACRpkda9R3c0dt95w0N7Fe5es16CqbWtsCKMaFq-nwSYV4bk-w@mail.gmail.com>
On Mon, Mar 05, 2012 at 09:50:51PM +0100, Linus Walleij wrote:
> On Mon, Mar 5, 2012 at 9:14 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>
> > This patch series cleans up the handling of cookies in DMA engine drivers.
> > This is done by providing a set of inline library functions for common
> > tasks:
>
> Overall this looks good, but I have a problem:
> patch [1/9] does not appear in any subscribed accounts (it may be on
> my @stericsson.com address, will check tomorrow)
Patch 1 is just a couple of line changes to mv_xor.[ch]
^ permalink raw reply
* RE: [PATCH 3/9] dmaengine: add private header file
From: H Hartley Sweeten @ 2012-03-05 23:28 UTC (permalink / raw)
To: Russell King - ARM Linux, Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <E1S4eK0-0000sv-87@rmk-PC.arm.linux.org.uk>
On Monday, March 05, 2012 1:16 PM, Russell King wrote:
>
> Add a local private header file to contain definitions and declarations
> which should only be used by DMA engine drivers.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
> drivers/dma/amba-pl08x.c | 2 ++
> drivers/dma/at_hdmac.c | 1 +
> drivers/dma/coh901318.c | 1 +
> drivers/dma/dmaengine.h | 10 ++++++++++
> drivers/dma/dw_dmac.c | 1 +
> drivers/dma/ep93xx_dma.c | 2 ++
> drivers/dma/fsldma.c | 1 +
> drivers/dma/imx-dma.c | 2 ++
> drivers/dma/imx-sdma.c | 2 ++
> drivers/dma/intel_mid_dma.c | 2 ++
> drivers/dma/ioat/dma.c | 2 ++
> drivers/dma/ioat/dma_v2.c | 2 ++
> drivers/dma/iop-adma.c | 2 ++
> drivers/dma/ipu/ipu_idmac.c | 1 +
> drivers/dma/mpc512x_dma.c | 2 ++
> drivers/dma/mv_xor.c | 2 ++
> drivers/dma/mxs-dma.c | 2 ++
> drivers/dma/pch_dma.c | 2 ++
> drivers/dma/pl330.c | 2 ++
> drivers/dma/ppc4xx/adma.c | 1 +
> drivers/dma/shdma.c | 2 ++
> drivers/dma/ste_dma40.c | 1 +
> drivers/dma/timb_dma.c | 2 ++
> drivers/dma/txx9dmac.c | 2 ++
> 24 files changed, 49 insertions(+), 0 deletions(-)
> create mode 100644 drivers/dma/dmaengine.h
>
> diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
> index 2b5121f..87475cb 100644
> --- a/drivers/dma/amba-pl08x.c
> +++ b/drivers/dma/amba-pl08x.c
> @@ -85,6 +85,8 @@
> #include <linux/slab.h>
> #include <asm/hardware/pl080.h>
> =20
> +#include "dmaengine.h"
> +
> #define DRIVER_NAME "pl08xdmac"
> =20
> static struct amba_driver pl08x_amba_driver;
> diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
> index 6baf5d7..ce26ba3 100644
> --- a/drivers/dma/at_hdmac.c
> +++ b/drivers/dma/at_hdmac.c
> @@ -27,6 +27,7 @@
> #include <linux/of_device.h>
> =20
> #include "at_hdmac_regs.h"
> +#include "dmaengine.h"
> =20
> /*
> * Glossary
> diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
> index 521434b..fb0d124 100644
> --- a/drivers/dma/coh901318.c
> +++ b/drivers/dma/coh901318.c
> @@ -24,6 +24,7 @@
> #include <mach/coh901318.h>
> =20
> #include "coh901318_lli.h"
> +#include "dmaengine.h"
> =20
> #define COHC_2_DEV(cohc) (&cohc->chan.dev->device)
> =20
> diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
> new file mode 100644
> index 0000000..968570d
> --- /dev/null
> +++ b/drivers/dma/dmaengine.h
> @@ -0,0 +1,10 @@
> +/*
> + * The contents of this file are private to DMA engine drivers, and is n=
ot
> + * part of the API to be used by DMA engine users.
> + */
> +#ifndef DMAENGINE_H
> +#define DMAENGINE_H
> +
> +#include <linux/dmaengine.h>
> +
> +#endif
Russell,
You have an include issue here.
All the dmaengine drivers have:
#include <linux/dmaengine.h>
Which is guarded with
#ifndef DMAENGINE_H
#define DMAENGINE_H
...
#endif
This is the same guard you are using in the private "dmaengine.h". And it
also includes <linux/dmaengine.h> again...
This doesn't compile as-is because the "dmaengine.h" file is not used due
to the #ifndef...
Regards,
Hartley
^ permalink raw reply
* RE: [PATCH 6/9] dmaengine: consolidate tx_status functions
From: H Hartley Sweeten @ 2012-03-05 23:35 UTC (permalink / raw)
To: Russell King - ARM Linux, Dan Williams, Vinod Koul
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Zhang Wei, Barry Song, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <E1S4eKz-0000tE-FB@rmk-PC.arm.linux.org.uk>
On Monday, March 05, 2012 1:17 PM, Russell King wrote:
>
> Now that we have the completed cookie in the dma_chan structure, we
> can consolidate the tx_status functions by providing a function to set
> the txstate structure and returning the DMA status. We also provide
> a separate helper to set the residue for cookies which are still in
> progress.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
<snip>
> diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
> index 47e0997..244a2c5 100644
> --- a/drivers/dma/dmaengine.h
> +++ b/drivers/dma/dmaengine.h
> @@ -45,4 +45,35 @@ static inline void dma_cookie_complete(struct dma_asyn=
c_tx_descriptor *tx)
> tx->cookie =3D 0;
> }
> =20
> +/**
> + * dma_cookie_status - report cookie status
> + * @chan: dma channel
> + * @cookie: cookie we are interested in
> + * @state: dma_tx_state structure to return last/used cookies
> + *
> + * Report the status of the cookie, filling in the state structure if
> + * non-NULL. No locking is required.
> + */
> +static inline enum dma_status dma_cookie_status(struct dma_chan *chan,
> + dma_cookie_t cookie, struct dma_tx_state *state)
> +{
> + dma_cookie_t used, complete;
> +
> + used =3D chan->cookie;
> + complete =3D chan->complete;
Is this supposed to be:
complete =3D chan->completed_cookie;
Regards,
Hartley
^ permalink raw reply
* RE: [PATCH 0/9] DMA engine cookie handling cleanups
From: H Hartley Sweeten @ 2012-03-05 23:44 UTC (permalink / raw)
To: Linus Walleij, Russell King - ARM Linux
Cc: Viresh Kumar, Stephen Warren, Linus Walleij, Srinidhi Kasagar,
Vinod Koul, Zhang Wei, Barry Song, Dan Williams,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <CACRpkda9R3c0dt95w0N7Fe5es16CqbWtsCKMaFq-nwSYV4bk-w@mail.gmail.com>
On Monday, March 05, 2012 1:51 PM, Linus Walleij wrote:
> On Mon, Mar 5, 2012 at 9:14 PM, Russell King - ARM Linux wrote:
>
>> This patch series cleans up the handling of cookies in DMA engine driver=
s.
>> This is done by providing a set of inline library functions for common
>> tasks:
>
> Overall this looks good, but I have a problem:
> patch [1/9] does not appear in any subscribed accounts (it may be on
> my @stericsson.com address, will check tomorrow)
Patch 8/9 also doesn't appear to be on the mailing list.
> One I get hold of an ungmangled copy I can test the series on
> ux500 and U300.
>
> Is it just stuck in moderation because of size or something like that?
I'm also trying to test the series on ep93xx but have some compile issues
with patches [3/9] and [6/9].
Regards,
Hartley
^ 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