* Re: [PATCH] mpc512x/clocks: initialize CAN clocks
From: Grant Likely @ 2009-11-02 18:02 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linuxppc-dev, Chen Hongjun, John Rigby, Wolfgang Denk
In-Reply-To: <1257175056-26093-1-git-send-email-w.sang@pengutronix.de>
Hi Wolfram,
Comments below
On Mon, Nov 2, 2009 at 8:17 AM, Wolfram Sang <w.sang@pengutronix.de> wrote:
> Signed-off-by: John Rigby <jrigby@freescale.com>
> Signed-off-by: Chen Hongjun <hong-jun.chen@freescale.com>
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---
>
> Should come after the fix for clk_get to be usable for the upcoming CAN d=
river:
> http://patchwork.ozlabs.org/patch/37342/
>
> =A0arch/powerpc/platforms/512x/clock.c | =A0 74 +++++++++++++++++++++++++=
++++++++++
> =A01 files changed, 74 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms=
/512x/clock.c
> index 4168457..2d3a5ef 100644
> --- a/arch/powerpc/platforms/512x/clock.c
> +++ b/arch/powerpc/platforms/512x/clock.c
> @@ -50,6 +50,8 @@ struct clk {
> =A0static LIST_HEAD(clocks);
> =A0static DEFINE_MUTEX(clocks_mutex);
>
> +struct clk mscan_clks[4];
> +
I'd rather not have more globals. If really needed, should at the
very least be static and prefixed with mpc5121_.
> =A0static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
> =A0{
> =A0 =A0 =A0 =A0struct clk *p, *clk =3D ERR_PTR(-ENOENT);
> @@ -119,6 +121,8 @@ struct mpc512x_clockctl {
> =A0 =A0 =A0 =A0u32 spccr; =A0 =A0 =A0 =A0 =A0 =A0 =A0/* SPDIF Clk Ctrl Re=
g */
> =A0 =A0 =A0 =A0u32 cccr; =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* CFM Clk Ctrl Reg =
*/
> =A0 =A0 =A0 =A0u32 dccr; =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* DIU Clk Cnfg Reg =
*/
> + =A0 =A0 =A0 /* rev2+ only regs */
> + =A0 =A0 =A0 u32 mccr[4]; =A0 =A0 =A0 =A0 =A0 =A0/* MSCAN Clk Ctrl Reg 1=
-4 */
> =A0};
>
> =A0struct mpc512x_clockctl __iomem *clockctl;
> @@ -688,6 +692,72 @@ static void psc_clks_init(void)
> =A0 =A0 =A0 =A0}
> =A0}
>
> +
> +/*
> + * mscan clock rate calculation
> + */
> +static unsigned long mscan_calc_rate(struct device_node *np, int mscannu=
m)
> +{
> + =A0 =A0 =A0 unsigned long mscanclk_src, mscanclk_div;
> + =A0 =A0 =A0 u32 *mccr =3D &clockctl->mccr[mscannum];
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* If the divider is the reset default of all 1's then
> + =A0 =A0 =A0 =A0* we know u-boot and/or board setup has not
> + =A0 =A0 =A0 =A0* done anything so set up a sane default
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (((in_be32(mccr) >> 17) & 0x7fff) =3D=3D 0x7fff) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* disable */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(mccr, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* src is sysclk, divider is 4 */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(mccr, (0x3 << 17) | 0x10000);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 switch ((in_be32(mccr) >> 14) & 0x3) {
> + =A0 =A0 =A0 case 0:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mscanclk_src =3D sys_clk.rate;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 1:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mscanclk_src =3D ref_clk.rate;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 2:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mscanclk_src =3D psc_mclk_in.rate;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 3:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mscanclk_src =3D spdif_txclk.rate;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
Nit: Table lookup perhaps?
> +
> + =A0 =A0 =A0 mscanclk_src =3D roundup(mscanclk_src, 1000000);
> + =A0 =A0 =A0 mscanclk_div =3D ((in_be32(mccr) >> 17) & 0x7fff) + 1;
> + =A0 =A0 =A0 return mscanclk_src / mscanclk_div;
> +}
> +
> +/*
> + * Find all silicon rev2 mscan nodes in device tree and assign a clock
> + * with name "mscan%d_clk" and dev pointing at the device
> + * returned from of_find_device_by_node
> + */
Comment block doesn't really help me understand what the function does.
> +static void mscan_clks_init(void)
> +{
> + =A0 =A0 =A0 struct device_node *np;
> + =A0 =A0 =A0 struct of_device *ofdev;
> + =A0 =A0 =A0 const u32 *cell_index;
> +
> + =A0 =A0 =A0 for_each_compatible_node(np, NULL, "fsl,mpc5121-mscan") {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cell_index =3D of_get_property(np, "cell-in=
dex", NULL);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (cell_index) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct clk *clk =3D &mscan_=
clks[*cell_index];
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk->flags =3D CLK_HAS_RATE=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ofdev =3D of_find_device_by=
_node(np);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk->dev =3D &ofdev->dev;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk->rate =3D mscan_calc_ra=
te(np, *cell_index);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sprintf(clk->name, "mscan%d=
_clk", *cell_index);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_register(clk);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +}
These clock controllers are 1:1 dedicated to the CAN devices, correct?
Wouldn't it make more sense to put this code directly into the CAN
bus device driver instead of in common code? And allocated the clk
structure at driver probe time? It seems like the only shared bit
seems to be access to the mccr registers.
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH] spi/mpc52xx: check for invalid PSC usage
From: Grant Likely @ 2009-11-02 18:03 UTC (permalink / raw)
To: Wolfram Sang; +Cc: spi-devel-general, David Brownell, linuxppc-dev
In-Reply-To: <20091102135244.GC4696@pengutronix.de>
On Mon, Nov 2, 2009 at 6:53 AM, Wolfram Sang <w.sang@pengutronix.de> wrote:
>> I wouldn't even bother. =A0It's not actively dangerous to try and use
>> PSC{4,5} in SPI mode. =A0It just not going to work. =A0Besides, the
>> MPC5200 common code already checks for an invalid PSC number when
>> setting the clock divisor.
>>
>> Have you seen cases of users trying to do the wrong thing with the
>> crippled PSCs?
>
> Yes, that was the reason for this patch :) How about this patch to give u=
sers a
> better idea than just -ENODEV via set_psc_clkdiv? ...[/me hacks]...
> Uuuh, there is even a bug which makes the case go unnoticed.
Sure. This looks okay to me. I'll pick it up.
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH] mpc512x/clocks: initialize CAN clocks
From: Wolfram Sang @ 2009-11-02 18:40 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, Chen Hongjun, John Rigby, Wolfgang Denk
In-Reply-To: <fa686aa40911021002x6d895606s57bca0f9fdd4e81b@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 776 bytes --]
> These clock controllers are 1:1 dedicated to the CAN devices, correct?
Yes.
> Wouldn't it make more sense to put this code directly into the CAN
> bus device driver instead of in common code? And allocated the clk
> structure at driver probe time?
Yes, just...
> It seems like the only shared bit seems to be access to the mccr registers.
...we can't access registers from two drivers?? Ah, wait, you are probably
aiming at moving the mscan_init-function to the can-driver and to expose the
mscan_calc_rate function from here? That sounds good in deed, will update!
Thanks,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH] mpc512x/clocks: initialize CAN clocks
From: Grant Likely @ 2009-11-02 21:13 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linuxppc-dev, Chen Hongjun, John Rigby, Wolfgang Denk
In-Reply-To: <20091102184023.GB3805@pengutronix.de>
On Mon, Nov 2, 2009 at 11:40 AM, Wolfram Sang <w.sang@pengutronix.de> wrote:
>> It seems like the only shared bit seems to be access to the mccr registers.
>
> ...we can't access registers from two drivers?? Ah, wait, you are probably
> aiming at moving the mscan_init-function to the can-driver and to expose the
> mscan_calc_rate function from here? That sounds good in deed, will update!
Yup, that is exactly my thinking.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH 08/28] Add SLB switching code for entry/exit
From: Alexander Graf @ 2009-11-02 22:02 UTC (permalink / raw)
To: kvm
Cc: Kevin Wolf, Arnd Bergmann, Hollis Blanchard, Marcelo Tosatti,
kvm-ppc, linuxppc-dev, Avi Kivity, bphilips, Olof Johansson
This is the really low level of guest entry/exit code.
Book3s_64 has an SLB, which stores all ESID -> VSID mappings we're
currently aware of.
The segments in the guest differ from the ones on the host, so we need
to switch the SLB to tell the MMU that we're in a new context.
So we store a shadow of the guest's SLB in the PACA, switch to that on
entry and only restore bolted entries on exit, leaving the rest to the
Linux SLB fault handler.
That way we get a really clean way of switching the SLB.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
v6 -> v7:
- use macros for slb bolt / unbolt
---
arch/powerpc/kvm/book3s_64_slb.S | 262 ++++++++++++++++++++++++++++++++++++++
1 files changed, 262 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/kvm/book3s_64_slb.S
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S
new file mode 100644
index 0000000..ecd237a
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_64_slb.S
@@ -0,0 +1,262 @@
+/*
+ * 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 SUSE Linux Products GmbH 2009
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#define SHADOW_SLB_ESID(num) (SLBSHADOW_SAVEAREA + (num * 0x10))
+#define SHADOW_SLB_VSID(num) (SLBSHADOW_SAVEAREA + (num * 0x10) + 0x8)
+#define UNBOLT_SLB_ENTRY(num) \
+ ld r9, SHADOW_SLB_ESID(num)(r12); \
+ /* Invalid? Skip. */; \
+ rldicl. r0, r9, 37, 63; \
+ beq slb_entry_skip_ ## num; \
+ xoris r9, r9, SLB_ESID_V@h; \
+ std r9, SHADOW_SLB_ESID(num)(r12); \
+ slb_entry_skip_ ## num:
+
+#define REBOLT_SLB_ENTRY(num) \
+ ld r10, SHADOW_SLB_ESID(num)(r11); \
+ cmpdi r10, 0; \
+ beq slb_exit_skip_1; \
+ oris r10, r10, SLB_ESID_V@h; \
+ ld r9, SHADOW_SLB_VSID(num)(r11); \
+ slbmte r9, r10; \
+ std r10, SHADOW_SLB_ESID(num)(r11); \
+slb_exit_skip_ ## num:
+
+/******************************************************************************
+ * *
+ * Entry code *
+ * *
+ *****************************************************************************/
+
+.global kvmppc_handler_trampoline_enter
+kvmppc_handler_trampoline_enter:
+
+ /* Required state:
+ *
+ * MSR = ~IR|DR
+ * R13 = PACA
+ * R9 = guest IP
+ * R10 = guest MSR
+ * R11 = free
+ * R12 = free
+ * PACA[PACA_EXMC + EX_R9] = guest R9
+ * PACA[PACA_EXMC + EX_R10] = guest R10
+ * PACA[PACA_EXMC + EX_R11] = guest R11
+ * PACA[PACA_EXMC + EX_R12] = guest R12
+ * PACA[PACA_EXMC + EX_R13] = guest R13
+ * PACA[PACA_EXMC + EX_CCR] = guest CR
+ * PACA[PACA_EXMC + EX_R3] = guest XER
+ */
+
+ mtsrr0 r9
+ mtsrr1 r10
+
+ mtspr SPRN_SPRG_SCRATCH0, r0
+
+ /* Remove LPAR shadow entries */
+
+#if SLB_NUM_BOLTED == 3
+
+ ld r12, PACA_SLBSHADOWPTR(r13)
+
+ /* Save off the first entry so we can slbie it later */
+ ld r10, SHADOW_SLB_ESID(0)(r12)
+ ld r11, SHADOW_SLB_VSID(0)(r12)
+
+ /* Remove bolted entries */
+ UNBOLT_SLB_ENTRY(0)
+ UNBOLT_SLB_ENTRY(1)
+ UNBOLT_SLB_ENTRY(2)
+
+#else
+#error unknown number of bolted entries
+#endif
+
+ /* Flush SLB */
+
+ slbia
+
+ /* r0 = esid & ESID_MASK */
+ rldicr r10, r10, 0, 35
+ /* r0 |= CLASS_BIT(VSID) */
+ rldic r12, r11, 56 - 36, 36
+ or r10, r10, r12
+ slbie r10
+
+ isync
+
+ /* Fill SLB with our shadow */
+
+ lbz r12, PACA_KVM_SLB_MAX(r13)
+ mulli r12, r12, 16
+ addi r12, r12, PACA_KVM_SLB
+ add r12, r12, r13
+
+ /* for (r11 = kvm_slb; r11 < kvm_slb + kvm_slb_size; r11+=slb_entry) */
+ li r11, PACA_KVM_SLB
+ add r11, r11, r13
+
+slb_loop_enter:
+
+ ld r10, 0(r11)
+
+ rldicl. r0, r10, 37, 63
+ beq slb_loop_enter_skip
+
+ ld r9, 8(r11)
+ slbmte r9, r10
+
+slb_loop_enter_skip:
+ addi r11, r11, 16
+ cmpd cr0, r11, r12
+ blt slb_loop_enter
+
+slb_do_enter:
+
+ /* Enter guest */
+
+ mfspr r0, SPRN_SPRG_SCRATCH0
+
+ ld r9, (PACA_EXMC+EX_R9)(r13)
+ ld r10, (PACA_EXMC+EX_R10)(r13)
+ ld r12, (PACA_EXMC+EX_R12)(r13)
+
+ lwz r11, (PACA_EXMC+EX_CCR)(r13)
+ mtcr r11
+
+ ld r11, (PACA_EXMC+EX_R3)(r13)
+ mtxer r11
+
+ ld r11, (PACA_EXMC+EX_R11)(r13)
+ ld r13, (PACA_EXMC+EX_R13)(r13)
+
+ RFI
+kvmppc_handler_trampoline_enter_end:
+
+
+
+/******************************************************************************
+ * *
+ * Exit code *
+ * *
+ *****************************************************************************/
+
+.global kvmppc_handler_trampoline_exit
+kvmppc_handler_trampoline_exit:
+
+ /* Register usage at this point:
+ *
+ * SPRG_SCRATCH0 = guest R13
+ * R01 = host R1
+ * R02 = host R2
+ * R10 = guest PC
+ * R11 = guest MSR
+ * R12 = exit handler id
+ * R13 = PACA
+ * PACA.exmc.CCR = guest CR
+ * PACA.exmc.R9 = guest R1
+ * PACA.exmc.R10 = guest R10
+ * PACA.exmc.R11 = guest R11
+ * PACA.exmc.R12 = guest R12
+ * PACA.exmc.R13 = guest R2
+ *
+ */
+
+ /* Save registers */
+
+ std r0, (PACA_EXMC+EX_SRR0)(r13)
+ std r9, (PACA_EXMC+EX_R3)(r13)
+ std r10, (PACA_EXMC+EX_LR)(r13)
+ std r11, (PACA_EXMC+EX_DAR)(r13)
+
+ /*
+ * In order for us to easily get the last instruction,
+ * we got the #vmexit at, we exploit the fact that the
+ * virtual layout is still the same here, so we can just
+ * ld from the guest's PC address
+ */
+
+ /* We only load the last instruction when it's safe */
+ cmpwi r12, BOOK3S_INTERRUPT_DATA_STORAGE
+ beq ld_last_inst
+ cmpwi r12, BOOK3S_INTERRUPT_PROGRAM
+ beq ld_last_inst
+
+ b no_ld_last_inst
+
+ld_last_inst:
+ /* Save off the guest instruction we're at */
+ /* 1) enable paging for data */
+ mfmsr r9
+ ori r11, r9, MSR_DR /* Enable paging for data */
+ mtmsr r11
+ /* 2) fetch the instruction */
+ lwz r0, 0(r10)
+ /* 3) disable paging again */
+ mtmsr r9
+
+no_ld_last_inst:
+
+ /* Restore bolted entries from the shadow and fix it along the way */
+
+ /* We don't store anything in entry 0, so we don't need to take care of it */
+ slbia
+ isync
+
+#if SLB_NUM_BOLTED == 3
+
+ ld r11, PACA_SLBSHADOWPTR(r13)
+
+ REBOLT_SLB_ENTRY(0)
+ REBOLT_SLB_ENTRY(1)
+ REBOLT_SLB_ENTRY(2)
+
+#else
+#error unknown number of bolted entries
+#endif
+
+slb_do_exit:
+
+ /* Restore registers */
+
+ ld r11, (PACA_EXMC+EX_DAR)(r13)
+ ld r10, (PACA_EXMC+EX_LR)(r13)
+ ld r9, (PACA_EXMC+EX_R3)(r13)
+
+ /* Save last inst */
+ stw r0, (PACA_EXMC+EX_LR)(r13)
+
+ /* Save DAR and DSISR before going to paged mode */
+ mfdar r0
+ std r0, (PACA_EXMC+EX_DAR)(r13)
+ mfdsisr r0
+ stw r0, (PACA_EXMC+EX_DSISR)(r13)
+
+ /* RFI into the highmem handler */
+ mfmsr r0
+ ori r0, r0, MSR_IR|MSR_DR|MSR_RI /* Enable paging */
+ mtsrr1 r0
+ ld r0, PACASAVEDMSR(r13) /* Highmem handler address */
+ mtsrr0 r0
+
+ mfspr r0, SPRN_SPRG_SCRATCH0
+
+ RFI
+kvmppc_handler_trampoline_exit_end:
+
--
1.6.0.2
^ permalink raw reply related
* [PATCH 20/28] Split init_new_context and destroy_context
From: Alexander Graf @ 2009-11-02 22:02 UTC (permalink / raw)
To: kvm
Cc: Kevin Wolf, Arnd Bergmann, Hollis Blanchard, Marcelo Tosatti,
kvm-ppc, linuxppc-dev, Avi Kivity, bphilips, Olof Johansson
In-Reply-To: <1257199351-2238-1-git-send-email-agraf@suse.de>
For KVM we need to allocate a new context id, but don't really care about
all the mm context around it.
So let's split the alloc and destroy functions for the context id, so we can
grab one without allocating an mm context.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
v6 -> v7:
- don't #ifdef twice
---
arch/powerpc/include/asm/mmu_context.h | 2 ++
arch/powerpc/mm/mmu_context_hash64.c | 24 +++++++++++++++++++++---
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index b34e94d..26383e0 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -23,6 +23,8 @@ extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
extern void set_context(unsigned long id, pgd_t *pgd);
#ifdef CONFIG_PPC_BOOK3S_64
+extern int __init_new_context(void);
+extern void __destroy_context(int context_id);
static inline void mmu_context_init(void) { }
#else
extern void mmu_context_init(void);
diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c
index dbeb86a..b9e4cc2 100644
--- a/arch/powerpc/mm/mmu_context_hash64.c
+++ b/arch/powerpc/mm/mmu_context_hash64.c
@@ -18,6 +18,7 @@
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
+#include <linux/module.h>
#include <asm/mmu_context.h>
@@ -32,7 +33,7 @@ static DEFINE_IDR(mmu_context_idr);
#define NO_CONTEXT 0
#define MAX_CONTEXT ((1UL << 19) - 1)
-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+int __init_new_context(void)
{
int index;
int err;
@@ -57,6 +58,18 @@ again:
return -ENOMEM;
}
+ return index;
+}
+EXPORT_SYMBOL_GPL(__init_new_context);
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+ int index;
+
+ index = __init_new_context();
+ if (index < 0)
+ return index;
+
/* The old code would re-promote on fork, we don't do that
* when using slices as it could cause problem promoting slices
* that have been forced down to 4K
@@ -68,11 +81,16 @@ again:
return 0;
}
-void destroy_context(struct mm_struct *mm)
+void __destroy_context(int context_id)
{
spin_lock(&mmu_context_lock);
- idr_remove(&mmu_context_idr, mm->context.id);
+ idr_remove(&mmu_context_idr, context_id);
spin_unlock(&mmu_context_lock);
+}
+EXPORT_SYMBOL_GPL(__destroy_context);
+void destroy_context(struct mm_struct *mm)
+{
+ __destroy_context(mm->context.id);
mm->context.id = NO_CONTEXT;
}
--
1.6.0.2
^ permalink raw reply related
* [PATCH 27/28] Use hrtimers for the decrementer
From: Alexander Graf @ 2009-11-02 22:02 UTC (permalink / raw)
To: kvm
Cc: Kevin Wolf, Arnd Bergmann, Hollis Blanchard, Marcelo Tosatti,
kvm-ppc, linuxppc-dev, Avi Kivity, bphilips, Olof Johansson
In-Reply-To: <1257199351-2238-1-git-send-email-agraf@suse.de>
Following S390's good example we should use hrtimers for the decrementer too!
This patch converts the timer from the old mechanism to hrtimers.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
v6 -> v7:
- remove non-hrtimer export
---
arch/powerpc/include/asm/kvm_host.h | 6 ++++--
arch/powerpc/kernel/ppc_ksyms.c | 3 +--
arch/powerpc/kvm/emulate.c | 18 +++++++++++-------
arch/powerpc/kvm/powerpc.c | 20 ++++++++++++++++++--
4 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 2cff5fe..1201f62 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -21,7 +21,8 @@
#define __POWERPC_KVM_HOST_H__
#include <linux/mutex.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/kvm_types.h>
#include <asm/kvm_asm.h>
@@ -250,7 +251,8 @@ struct kvm_vcpu_arch {
u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
- struct timer_list dec_timer;
+ struct hrtimer dec_timer;
+ struct tasklet_struct tasklet;
u64 dec_jiffies;
unsigned long pending_exceptions;
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index baf778c..c8b27bb 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -163,12 +163,11 @@ EXPORT_SYMBOL(screen_info);
#ifdef CONFIG_PPC32
EXPORT_SYMBOL(timer_interrupt);
EXPORT_SYMBOL(irq_desc);
+EXPORT_SYMBOL(tb_ticks_per_jiffy);
EXPORT_SYMBOL(cacheable_memcpy);
EXPORT_SYMBOL(cacheable_memzero);
#endif
-EXPORT_SYMBOL(tb_ticks_per_jiffy);
-
#ifdef CONFIG_PPC32
EXPORT_SYMBOL(switch_mmu_context);
#endif
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 1ec5e07..4a9ac66 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -18,7 +18,7 @@
*/
#include <linux/jiffies.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kvm_host.h>
@@ -79,12 +79,13 @@ static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
{
- unsigned long nr_jiffies;
+ unsigned long dec_nsec;
+ pr_debug("mtDEC: %x\n", vcpu->arch.dec);
#ifdef CONFIG_PPC64
/* POWER4+ triggers a dec interrupt if the value is < 0 */
if (vcpu->arch.dec & 0x80000000) {
- del_timer(&vcpu->arch.dec_timer);
+ hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
kvmppc_core_queue_dec(vcpu);
return;
}
@@ -94,12 +95,15 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
* that's how we convert the guest DEC value to the number of
* host ticks. */
+ hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+ dec_nsec = vcpu->arch.dec;
+ dec_nsec *= 1000;
+ dec_nsec /= tb_ticks_per_usec;
+ hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
+ HRTIMER_MODE_REL);
vcpu->arch.dec_jiffies = get_tb();
- nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
- mod_timer(&vcpu->arch.dec_timer,
- get_jiffies_64() + nr_jiffies);
} else {
- del_timer(&vcpu->arch.dec_timer);
+ hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
}
}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 4ae3490..4c582ed 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -23,6 +23,7 @@
#include <linux/kvm_host.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
+#include <linux/hrtimer.h>
#include <linux/fs.h>
#include <asm/cputable.h>
#include <asm/uaccess.h>
@@ -209,10 +210,25 @@ static void kvmppc_decrementer_func(unsigned long data)
}
}
+/*
+ * low level hrtimer wake routine. Because this runs in hardirq context
+ * we schedule a tasklet to do the real work.
+ */
+enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer)
+{
+ struct kvm_vcpu *vcpu;
+
+ vcpu = container_of(timer, struct kvm_vcpu, arch.dec_timer);
+ tasklet_schedule(&vcpu->arch.tasklet);
+
+ return HRTIMER_NORESTART;
+}
+
int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
{
- setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func,
- (unsigned long)vcpu);
+ hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+ tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
+ vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
return 0;
}
--
1.6.0.2
^ permalink raw reply related
* Re: Filtering bits in set_pte_at()
From: Benjamin Herrenschmidt @ 2009-11-02 22:19 UTC (permalink / raw)
To: Hugh Dickins
Cc: linux-mm@kvack.org, linuxppc-dev, linux-kernel@vger.kernel.org
In-Reply-To: <Pine.LNX.4.64.0911021256330.32400@sister.anvils>
On Mon, 2009-11-02 at 13:27 +0000, Hugh Dickins wrote:
> On Sat, 31 Oct 2009, Benjamin Herrenschmidt wrote:
>
> > Hi folks !
> >
> > So I have a little problem on powerpc ... :-)
>
> Thanks a lot for running this by us.
Heh, I though you may have been bored :-)
> I've not looked to see if there are more such issues in arch/powerpc
> itself, but those instances you mention are the only ones I managed
> to find: uses of update_mmu_cache() and that hugetlb_cow() one.
Right, that's all I spotted so far
> The hugetlb_cow() one involves not set_pte_at() but set_huge_pte_at(),
> so you'd want to change that too? And presumably set_pte_at_notify()?
> It all seems a lot of tedium, when so very few places are interested
> in the pte after they've set it.
We need to change set_huge_pte_at() too. Currently, David fixed the
problem in a local tree by making hugetlb_cow() re-read the PTE .
set_pte_at_notify() would probably be similar, I'm not too familiar with
its usage scenario yet to be honest.
> > What do you suggest we do here ? Among the options at hand:
> >
> > - Ugly but would probably "just work" with the last amount of changes:
> > we could make set_pte_at() be a macro on powerpc that modifies it's PTE
> > value argument :-) (I -did- warn it was ugly !)
>
> I'm not keen on that one :)
Yeah. Me neither :-)
> > - Another one slightly less bad that would require more work but mostly
> > mechanical arch header updates would be to make set_pte_at() return the
> > new value of the PTE, and thus change the callsites to something like:
> >
> > entry = set_pte_at(mm, addr, ptep, entry)
>
> I prefer that, but it still seems more trouble than it's worth.
Right. I was hoping you might have a better idea :-)
> And though I prefer it to set_pte_at(mm, addr, ptep, &entry)
> (which would anyway complicate many of the callsites), it might
> unnecessarily increase the codesize for all architectures (depends
> on whether gcc notices entry isn't used afterwards anyway).
Macro or static inlines back to __set_pte_at(..., entry) in those archs
would probably take care of avoiding the bloat but still a lot of churn.
> >
> > - Any other idea ? We could use another PTE bit (_PAGE_HWEXEC), in
> > fact, we used to, but we are really short on PTE bits nowadays and I
> > freed that one up to get _PAGE_SPECIAL... _PAGE_EXEC is trivial to
> > "recover" from ptep_set_access_flags() on an exec fault or from the VM
> > prot.
>
> No, please don't go ransacking your PTE for a sparish bit.
Yeah, the whole exercise for me was initially to -save- PTE bits :-)
> You're being a very good citizen to want to bring this so forcefully
> to the attention of any user of set_pte_at(); but given how few care,
> and the other such functions you'd want to change too, am I being
> disgracefully lazy to suggest that you simply change the occasional
>
> update_mmu_cache(vma, address, pte);
> to
> /* powerpc's set_pte_at might have adjusted the pte */
> update_mmu_cache(vma, address, *ptep);
>
> ? Which would make no difference to those architectures whose
> update_mmu_cache() is an empty macro. And fix the mm/hugetlb.c
> instance in a similar way?
That would do fine. In fact, I've always been slightly annoyed by
set_pte_at() not taking the PTE pointer for other reasons such as on
64-K pages, we have a "hidden" part of the PTE that is at PTE address +
32K, or we may want to get to the PTE page for some reason (some arch
store things there) etc...
IE. update_mmu_cache() would be more generally useful if it took the
ptep instead of the pte. Of course, I'm sure some embedded archs are
going to cry for the added load here ...
I like your idea. I'll look into doing a patch converting it and will
post it here.
Thanks !
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH V2] mpc512x/clock: fix clk_get logic
From: Stephen Rothwell @ 2009-11-02 23:10 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, Roel Kluin, Wolfgang Denk, Mark Brown
In-Reply-To: <fa686aa40911020948o673b058emba4bb2ccfc1cfd17@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 398 bytes --]
Hi Grant,
On Mon, 2 Nov 2009 10:48:58 -0700 Grant Likely <grant.likely@secretlab.ca> wrote:
>
> Using bool/true/false doesn't seem to be a common pattern in the
> kernel. Anyone know what the winds of prevailing opinion are
> regarding 'bool' in kernel code?
Its a good thing.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: Filtering bits in set_pte_at()
From: Hugh Dickins @ 2009-11-02 23:45 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-mm@kvack.org, linuxppc-dev, linux-kernel@vger.kernel.org
In-Reply-To: <1257200367.7907.50.camel@pasglop>
On Tue, 3 Nov 2009, Benjamin Herrenschmidt wrote:
> On Mon, 2009-11-02 at 13:27 +0000, Hugh Dickins wrote:
>
> > You're being a very good citizen to want to bring this so forcefully
> > to the attention of any user of set_pte_at(); but given how few care,
> > and the other such functions you'd want to change too, am I being
> > disgracefully lazy to suggest that you simply change the occasional
> >
> > update_mmu_cache(vma, address, pte);
> > to
> > /* powerpc's set_pte_at might have adjusted the pte */
> > update_mmu_cache(vma, address, *ptep);
> >
> > ? Which would make no difference to those architectures whose
> > update_mmu_cache() is an empty macro. And fix the mm/hugetlb.c
> > instance in a similar way?
>
> That would do fine. In fact, I've always been slightly annoyed by
> set_pte_at() not taking the PTE pointer for other reasons such as on
> 64-K pages, we have a "hidden" part of the PTE that is at PTE address +
> 32K, or we may want to get to the PTE page for some reason (some arch
> store things there) etc...
>
> IE. update_mmu_cache() would be more generally useful if it took the
> ptep instead of the pte. Of course, I'm sure some embedded archs are
> going to cry for the added load here ...
>
> I like your idea. I'll look into doing a patch converting it and will
> post it here.
Well, I wasn't proposing
update_mmu_cache(vma, address, ptep);
but
update_mmu_cache(vma, address, *ptep);
which may not meet your future idea, but is much less churn for now
i.e. no change to any of the arch's update_mmu_cache(),
just a change to some of its callsites.
Hugh
^ permalink raw reply
* Re: [PATCH V2] mpc512x/clock: fix clk_get logic
From: Grant Likely @ 2009-11-02 23:49 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linuxppc-dev, Roel Kluin, Wolfgang Denk, Mark Brown
In-Reply-To: <20091103101032.496a0290.sfr@canb.auug.org.au>
On Mon, Nov 2, 2009 at 4:10 PM, Stephen Rothwell <sfr@canb.auug.org.au> wro=
te:
> Hi Grant,
>
> On Mon, 2 Nov 2009 10:48:58 -0700 Grant Likely <grant.likely@secretlab.ca=
> wrote:
>>
>> Using bool/true/false doesn't seem to be a common pattern in the
>> kernel. =A0Anyone know what the winds of prevailing opinion are
>> regarding 'bool' in kernel code?
>
> Its a good thing.
Thanks,
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: mpc8548 does not make use of DMA when doing memory copy?
From: hank peng @ 2009-11-03 0:35 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <15E6E326-D17B-42D7-AA22-2CA319C2A808@kernel.crashing.org>
2009/11/3 Kumar Gala <galak@kernel.crashing.org>:
>
> On Nov 2, 2009, at 9:40 AM, hank peng wrote:
>
>> Kernel version is 2.6.30 and I have enabled fsl DMA engine during
>> configuring kernel. After system booted, I have seen only 38 DMA
>> interrupts, and no increase later when I am doing data transfer
>> through network.
>> So I wonder if mpc8548 =C2=A0had made use of DMA engine when doing memcp=
y,
>> or maybe if there are other things I haven't noticed?
>
> The dma engine code is not normally used for normal memcpy's in the kerne=
l.
> =C2=A0There are explicit call sites that have async behavior that should =
use it
> (like the networking code).
>
I remember normal memory copy can also be done (chosen by user) by DMA
engine on IOP80331(Intel embedded cpu, xscale arch), so why ppc
platform didn't make use of DMA doing memory copy, I think it can
increase performance, please correct me if I am wrong!
> - k
>
--=20
The simplest is not all best but the best is surely the simplest!
^ permalink raw reply
* Re: [PATCH v0 2/2] Crypto: Talitos: Support for Async_tx XOR offload
From: hank peng @ 2009-11-03 0:43 UTC (permalink / raw)
To: Dan Williams
Cc: herbert, linux-kernel, linux-raid, linuxppc-dev, Vishnu Suresh,
linux-crypto, Dipen Dudhat, Maneesh Gupta
In-Reply-To: <e9c3a7c20910291546r2603e191g87a23023c32f1b1b@mail.gmail.com>
I have tested this patch on my MPC8548 machine box, kernel version is
2.6.30. There is a problem.
#mdadm -C /dev/md0 -l5 -n3 /dev/sd{a,b,c}
Recovery can be done successfully, interrupts looks normal.
# cat /proc/interrupts
CPU0
16: 16091057 OpenPIC Level mvSata
17: 0 OpenPIC Level mvSata
18: 4 OpenPIC Level phy_interrupt, phy_interrupt
20: 39 OpenPIC Level fsldma-channel
21: 0 OpenPIC Level fsldma-channel
22: 0 OpenPIC Level fsldma-channel
23: 0 OpenPIC Level fsldma-channel
29: 241 OpenPIC Level eth0_tx
30: 1004692 OpenPIC Level eth0_rx
34: 0 OpenPIC Level eth0_er
35: 0 OpenPIC Level eth1_tx
36: 0 OpenPIC Level eth1_rx
40: 0 OpenPIC Level eth1_er
42: 73060 OpenPIC Level serial
43: 9854 OpenPIC Level i2c-mpc, i2c-mpc
45: 61264188 OpenPIC Level talitos
BAD: 0
Then, I plan to create a VG, but problem occured.
#pvcreate /dev/md0
After I input this command, system hangs there without any messages.
BTW, all is OK before using this patch.
2009/10/30 Dan Williams <dan.j.williams@intel.com>:
> On Wed, Oct 14, 2009 at 11:41 PM, Vishnu Suresh <Vishnu@freescale.com> wr=
ote:
> [..]
>> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
>> index b08403d..343e578 100644
>> --- a/drivers/crypto/Kconfig
>> +++ b/drivers/crypto/Kconfig
>> @@ -192,6 +192,8 @@ config CRYPTO_DEV_TALITOS
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0select CRYPTO_ALGAPI
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0select CRYPTO_AUTHENC
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0select HW_RANDOM
>> + =C2=A0 =C2=A0 =C2=A0 select DMA_ENGINE
>> + =C2=A0 =C2=A0 =C2=A0 select ASYNC_XOR
>
> You need only select DMA_ENGINE. =C2=A0ASYNC_XOR is selected by its users=
.
>
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0depends on FSL_SOC
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0help
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Say 'Y' here to use the Freescale Secu=
rity Engine (SEC)
>> diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
>> index c47ffe8..84819d4 100644
>> --- a/drivers/crypto/talitos.c
>> +++ b/drivers/crypto/talitos.c
> [..]
>> +static void talitos_process_pending(struct talitos_xor_chan *xor_chan)
>> +{
>> + =C2=A0 =C2=A0 =C2=A0 struct talitos_xor_desc *desc, *_desc;
>> + =C2=A0 =C2=A0 =C2=A0 unsigned long flags;
>> + =C2=A0 =C2=A0 =C2=A0 int status;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 spin_lock_irqsave(&xor_chan->desc_lock, flags);
>> +
>> + =C2=A0 =C2=A0 =C2=A0 list_for_each_entry_safe(desc, _desc, &xor_chan->=
pending_q, node) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 status =3D talitos_su=
bmit(xor_chan->dev, &desc->hwdesc,
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 talitos_rele=
ase_xor, desc);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (status !=3D -EINP=
ROGRESS)
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 break;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 list_del(&desc->node)=
;
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 list_add_tail(&desc->=
node, &xor_chan->in_progress_q);
>> + =C2=A0 =C2=A0 =C2=A0 }
>> +
>> + =C2=A0 =C2=A0 =C2=A0 spin_unlock_irqrestore(&xor_chan->desc_lock, flag=
s);
>> +}
>
> The driver uses spin_lock_bh everywhere else which is either a bug, or
> this code is being overly protective. =C2=A0In any event lockdep will
> rightly complain about this. =C2=A0The API and its users do not submit
> operations in hard-irq context.
>
>> +
>> +static void talitos_release_xor(struct device *dev, struct talitos_desc=
*hwdesc,
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void *context, int error)
>> +{
>> + =C2=A0 =C2=A0 =C2=A0 struct talitos_xor_desc *desc =3D context;
>> + =C2=A0 =C2=A0 =C2=A0 struct talitos_xor_chan *xor_chan;
>> + =C2=A0 =C2=A0 =C2=A0 dma_async_tx_callback callback;
>> + =C2=A0 =C2=A0 =C2=A0 void *callback_param;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 if (unlikely(error)) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 dev_err(dev, "xor ope=
ration: talitos error %d\n", error);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 BUG();
>> + =C2=A0 =C2=A0 =C2=A0 }
>> +
>> + =C2=A0 =C2=A0 =C2=A0 xor_chan =3D container_of(desc->async_tx.chan, st=
ruct talitos_xor_chan,
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 common);
>> + =C2=A0 =C2=A0 =C2=A0 spin_lock_bh(&xor_chan->desc_lock);
>> + =C2=A0 =C2=A0 =C2=A0 if (xor_chan->completed_cookie < desc->async_tx.c=
ookie)
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 xor_chan->completed_c=
ookie =3D desc->async_tx.cookie;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 callback =3D desc->async_tx.callback;
>> + =C2=A0 =C2=A0 =C2=A0 callback_param =3D desc->async_tx.callback_param;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 if (callback) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 spin_unlock_bh(&xor_c=
han->desc_lock);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 callback(callback_par=
am);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 spin_lock_bh(&xor_cha=
n->desc_lock);
>> + =C2=A0 =C2=A0 =C2=A0 }
>
> You do not need to unlock to call the callback. =C2=A0Users of the API
> assume that they are called in bh context and that they are not
> allowed to submit new operations directly from the callback (this
> simplifies the descriptor cleanup routines in other drivers).
>
>> +
>> + =C2=A0 =C2=A0 =C2=A0 list_del(&desc->node);
>> + =C2=A0 =C2=A0 =C2=A0 list_add_tail(&desc->node, &xor_chan->free_desc);
>> + =C2=A0 =C2=A0 =C2=A0 spin_unlock_bh(&xor_chan->desc_lock);
>> + =C2=A0 =C2=A0 =C2=A0 if (!list_empty(&xor_chan->pending_q))
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 talitos_process_pendi=
ng(xor_chan);
>> +}
>
> It appears this routine is missing a call to dma_run_dependencies()?
> This is needed if another channel is handling memory copy offload. =C2=A0=
I
> assume this is the case due to your other patch to fsldma. =C2=A0See
> iop_adma_run_tx_complete_actions(). =C2=A0If this xor resource can also
> handle copy operations that would be more efficient as it eliminates
> channel switching. =C2=A0See the ioatdma driver and its use of
> ASYNC_TX_DISABLE_CHANNEL_SWITCH.
>
>> +static struct dma_async_tx_descriptor * talitos_prep_dma_xor(
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 unsigned int src_cnt, size_t len, unsigned long flags)
>> +{
>> + =C2=A0 =C2=A0 =C2=A0 struct talitos_xor_chan *xor_chan;
>> + =C2=A0 =C2=A0 =C2=A0 struct talitos_xor_desc *new;
>> + =C2=A0 =C2=A0 =C2=A0 struct talitos_desc *desc;
>> + =C2=A0 =C2=A0 =C2=A0 int i, j;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 BUG_ON(unlikely(len > TALITOS_MAX_DATA_LEN));
>> +
>> + =C2=A0 =C2=A0 =C2=A0 xor_chan =3D container_of(chan, struct talitos_xo=
r_chan, common);
>> +
>> + =C2=A0 =C2=A0 =C2=A0 spin_lock_bh(&xor_chan->desc_lock);
>> + =C2=A0 =C2=A0 =C2=A0 if (!list_empty(&xor_chan->free_desc)) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 new =3D container_of(=
xor_chan->free_desc.next,
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct talitos_xor_desc, no=
de);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 list_del(&new->node);
>> + =C2=A0 =C2=A0 =C2=A0 } else {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 new =3D talitos_xor_a=
lloc_descriptor(xor_chan, GFP_KERNEL);
>> + =C2=A0 =C2=A0 =C2=A0 }
>> + =C2=A0 =C2=A0 =C2=A0 spin_unlock_bh(&xor_chan->desc_lock);
>> +
>> + =C2=A0 =C2=A0 =C2=A0 if (!new) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 dev_err(xor_chan->com=
mon.device->dev,
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 "No free memory for XOR DMA descriptor\n");
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return NULL;
>> + =C2=A0 =C2=A0 =C2=A0 }
>> + =C2=A0 =C2=A0 =C2=A0 dma_async_tx_descriptor_init(&new->async_tx, &xor=
_chan->common);
>> +
>> + =C2=A0 =C2=A0 =C2=A0 INIT_LIST_HEAD(&new->node);
>> + =C2=A0 =C2=A0 =C2=A0 INIT_LIST_HEAD(&new->tx_list);
>
> You can save some overhead in the fast path by moving this
> initialization to talitos_xor_alloc_descriptor.
>
>> +
>> + =C2=A0 =C2=A0 =C2=A0 desc =3D &new->hwdesc;
>> + =C2=A0 =C2=A0 =C2=A0 /* Set destination: Last pointer pair */
>> + =C2=A0 =C2=A0 =C2=A0 to_talitos_ptr(&desc->ptr[6], dest);
>> + =C2=A0 =C2=A0 =C2=A0 desc->ptr[6].len =3D cpu_to_be16(len);
>> + =C2=A0 =C2=A0 =C2=A0 desc->ptr[6].j_extent =3D 0;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 /* Set Sources: End loading from second-last poin=
ter pair */
>> + =C2=A0 =C2=A0 =C2=A0 for (i =3D 5, j =3D 0; (j < src_cnt) && (i > 0); =
i--, j++) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to_talitos_ptr(&desc-=
>ptr[i], src[j]);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 desc->ptr[i].len =3D =
cpu_to_be16(len);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 desc->ptr[i].j_extent=
=3D 0;
>> + =C2=A0 =C2=A0 =C2=A0 }
>> +
>> + =C2=A0 =C2=A0 =C2=A0 /*
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0* documentation states first 0 ptr/len comb=
o marks end of sources
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0* yet device produces scatter boundary erro=
r unless all subsequent
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0* sources are zeroed out
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0*/
>> + =C2=A0 =C2=A0 =C2=A0 for (; i >=3D 0; i--) {
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to_talitos_ptr(&desc-=
>ptr[i], 0);
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 desc->ptr[i].len =3D =
0;
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 desc->ptr[i].j_extent=
=3D 0;
>> + =C2=A0 =C2=A0 =C2=A0 }
>> +
>> + =C2=A0 =C2=A0 =C2=A0 desc->hdr =3D DESC_HDR_SEL0_AESU | DESC_HDR_MODE0=
_AESU_XOR
>> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | DESC_=
HDR_TYPE_RAID_XOR;
>> +
>> + =C2=A0 =C2=A0 =C2=A0 new->async_tx.parent =3D NULL;
>> + =C2=A0 =C2=A0 =C2=A0 new->async_tx.next =3D NULL;
>
> These fields are managed by the async_tx channel switch code. =C2=A0No ne=
ed
> to manage it here.
>
>> + =C2=A0 =C2=A0 =C2=A0 new->async_tx.cookie =3D 0;
>
> This is set below to -EBUSY, it's redundant to touch it here.
>
>> + =C2=A0 =C2=A0 =C2=A0 async_tx_ack(&new->async_tx);
>
> This makes it impossible to attach a dependency to this operation.
> Not sure this is what you want.
>
> --
> Dan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-raid" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at =C2=A0http://vger.kernel.org/majordomo-info.html
>
--=20
The simplest is not all best but the best is surely the simplest!
^ permalink raw reply
* Re: Filtering bits in set_pte_at()
From: Benjamin Herrenschmidt @ 2009-11-03 1:22 UTC (permalink / raw)
To: Hugh Dickins
Cc: linux-mm@kvack.org, linuxppc-dev, linux-kernel@vger.kernel.org
In-Reply-To: <Pine.LNX.4.64.0911022342070.30581@sister.anvils>
On Mon, 2009-11-02 at 23:45 +0000, Hugh Dickins wrote:
> > IE. update_mmu_cache() would be more generally useful if it took the
> > ptep instead of the pte. Of course, I'm sure some embedded archs are
> > going to cry for the added load here ...
> >
> > I like your idea. I'll look into doing a patch converting it and
> will
> > post it here.
>
> Well, I wasn't proposing
>
> update_mmu_cache(vma, address, ptep);
> but
> update_mmu_cache(vma, address, *ptep);
>
> which may not meet your future idea, but is much less churn for now
> i.e. no change to any of the arch's update_mmu_cache(),
> just a change to some of its callsites.
I see... but if we go that way, I think we may as well do the whole
churn... I'll have a look at how bad it is.
Cheers,
Ben.
^ permalink raw reply
* enabling USB Host controller on ppc405ex based board
From: Jignesh Patel @ 2009-11-03 3:04 UTC (permalink / raw)
To: linuxppc-dev@lists.ozlabs.org; +Cc: Mukunda Saddi
Hi,
We have Kilauea based board using ppc405ex. & it has usb-otg tranciever chi=
p on it.
I am trying to enable USB Host Controller Driver in linux kernel (version D=
ENX 2.6.27-stable). For this to be enabled, I also have to enable PCI in k=
ernel config.
But when I load the kernel uImage with both USB Host Controller & PCI optio=
ns selected in kernel config, the board doesn't boot up properly. Boot proc=
ess halts after loading device tree.
When I load the kernel without PCI options selected, kernel boots up proper=
ly. But removing PCI config option also removes USB Host Controller option=
s in kernel.
My questions are:
1. Why is PCI config required for USB Host Controller options to be enabled=
in kernel config?
2. What needs to be done to boot our board with PCI & USB enabled kernel?
Best regards,
-Jignesh=
^ permalink raw reply
* Re: enabling USB Host controller on ppc405ex based board
From: Wolfgang Denk @ 2009-11-03 7:33 UTC (permalink / raw)
To: Jignesh Patel; +Cc: Mukunda Saddi, linuxppc-dev@lists.ozlabs.org, eldk
In-Reply-To: <D7C6597E47CDAD4BA48EE3D2B03B385102E7C3CE9D@VMBX113.ihostexchange.net>
Dear Jignesh Patel,
please do not post the same messages several times to several mailing
lists.
In message <D7C6597E47CDAD4BA48EE3D2B03B385102E7C3CE9D@VMBX113.ihostexchange.net> you wrote:
>
> We have Kilauea based board using ppc405ex. & it has usb-otg
> tranciever chip on it.
>
> I am trying to enable USB Host Controller Driver in linux kernel
> (version DENX 2.6.27-stable). For this to be enabled, I also have to
Please note that the Synopsys USB driver in our tree has not been
maintained for a long time. Over time, it detoriated. Only recently
we have put some more efforts into it to at least make it work again.
It still is in a pretty poor state, which is the main reason we never
attempted to push this upstream. [In my opinion it needs to be
rewritten from scratch.]
For the relevant changes please see for example
http://git.denx.de/?p=linux-2.6-denx.git;a=commit;h=126bae384eacef18bcae302024d49e25a06cb648
> My questions are:
> 1. Why is PCI config required for USB Host Controller options to be enabled in kernel config?
> 2. What needs to be done to boot our board with PCI & USB enabled kernel?
Please use a more recent kernel version - either use top of tree from
the master branch of our repository, or a recent version from our
2.6.30.y or 2.6.31.y stable branches, i. e at least DENX-v2.6.30.3 or
DENX-v2.6.31.4
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Conceptual integrity in turn dictates that the design must proceed
from one mind, or from a very small number of agreeing resonant
minds. - Frederick Brooks Jr., "The Mythical Man Month"
^ permalink raw reply
* Re: [PATCH 14/27] Add book3s_64 specific opcode emulation
From: Segher Boessenkool @ 2009-11-03 8:47 UTC (permalink / raw)
To: Alexander Graf
Cc: Kevin Wolf, Arnd Bergmann, Hollis Blanchard, Marcelo Tosatti,
kvm-ppc, linuxppc-dev, Avi Kivity, kvm, bphilips, Olof Johansson
In-Reply-To: <1256917647-6200-15-git-send-email-agraf@suse.de>
Nice patchset. Some comments on the emulation part:
> +#define OP_31_XOP_EIOIO 854
You mean EIEIO.
> + case 19:
> + switch (get_xop(inst)) {
> + case OP_19_XOP_RFID:
> + case OP_19_XOP_RFI:
> + vcpu->arch.pc = vcpu->arch.srr0;
> + kvmppc_set_msr(vcpu, vcpu->arch.srr1);
> + *advance = 0;
> + break;
I think you should only emulate the insns that exist on whatever the
guest
pretends to be. RFID exist only on 64-bit implementations. Same
comment
everywhere else.
> + case OP_31_XOP_EIOIO:
> + break;
Have you always executed an eieio or sync when you get here, or
do you just not allow direct access to I/O devices? Other context
synchronising insns are not enough, they do not broadcast on the
bus.
> + case OP_31_XOP_DCBZ:
> + {
> + ulong rb = vcpu->arch.gpr[get_rb(inst)];
> + ulong ra = 0;
> + ulong addr;
> + u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
> +
> + if (get_ra(inst))
> + ra = vcpu->arch.gpr[get_ra(inst)];
> +
> + addr = (ra + rb) & ~31ULL;
> + if (!(vcpu->arch.msr & MSR_SF))
> + addr &= 0xffffffff;
> +
> + if (kvmppc_st(vcpu, addr, 32, zeros)) {
DCBZ zeroes out a cache line, not 32 bytes; except on 970, where there
are HID bits to make it work on 32 bytes only, and an extra DCBZL insn
that always clears a full cache line (128 bytes).
> + switch (sprn) {
> + case SPRN_IBAT0U ... SPRN_IBAT3L:
> + bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2];
> + break;
> + case SPRN_IBAT4U ... SPRN_IBAT7L:
> + bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT4U) / 2];
> + break;
> + case SPRN_DBAT0U ... SPRN_DBAT3L:
> + bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2];
> + break;
> + case SPRN_DBAT4U ... SPRN_DBAT7L:
> + bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT4U) / 2];
> + break;
Do xBAT4..7 have the same SPR numbers on all CPUs? They are CPU-
specific
SPRs, after all. Some CPUs have only six, some only four, some none,
btw.
> + case SPRN_HID0:
> + to_book3s(vcpu)->hid[0] = vcpu->arch.gpr[rs];
> + break;
> + case SPRN_HID1:
> + to_book3s(vcpu)->hid[1] = vcpu->arch.gpr[rs];
> + break;
> + case SPRN_HID2:
> + to_book3s(vcpu)->hid[2] = vcpu->arch.gpr[rs];
> + break;
> + case SPRN_HID4:
> + to_book3s(vcpu)->hid[4] = vcpu->arch.gpr[rs];
> + break;
> + case SPRN_HID5:
> + to_book3s(vcpu)->hid[5] = vcpu->arch.gpr[rs];
HIDs are different per CPU; and worse, different CPUs have different
registers (SPR #s) for the same register name!
> + /* guest HID5 set can change is_dcbz32 */
> + if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
> + (mfmsr() & MSR_HV))
> + vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
> + break;
Wait, does this mean you allow other HID writes when MSR[HV] isn't
set? All HIDs (and many other SPRs) cannot be read or written in
supervisor mode.
Segher
^ permalink raw reply
* Re: [PATCH 14/27] Add book3s_64 specific opcode emulation
From: Alexander Graf @ 2009-11-03 9:06 UTC (permalink / raw)
To: Segher Boessenkool
Cc: Kevin Wolf, Arnd Bergmann, Hollis Blanchard, Marcelo Tosatti,
kvm-ppc, linuxppc-dev, Avi Kivity, kvm, bphilips, Olof Johansson
In-Reply-To: <A1CBD511-FF08-48BB-A8D6-9F66E20F770B@kernel.crashing.org>
On 03.11.2009, at 09:47, Segher Boessenkool wrote:
> Nice patchset. Some comments on the emulation part:
Cool, thanks for looking though them!
>> +#define OP_31_XOP_EIOIO 854
>
> You mean EIEIO.
Probably, yeah.
>> + case 19:
>> + switch (get_xop(inst)) {
>> + case OP_19_XOP_RFID:
>> + case OP_19_XOP_RFI:
>> + vcpu->arch.pc = vcpu->arch.srr0;
>> + kvmppc_set_msr(vcpu, vcpu->arch.srr1);
>> + *advance = 0;
>> + break;
>
> I think you should only emulate the insns that exist on whatever the
> guest
> pretends to be. RFID exist only on 64-bit implementations. Same
> comment
> everywhere else.
True.
>
>> + case OP_31_XOP_EIOIO:
>> + break;
>
> Have you always executed an eieio or sync when you get here, or
> do you just not allow direct access to I/O devices? Other context
> synchronising insns are not enough, they do not broadcast on the
> bus.
There is no device passthrough yet :-). It's theoretically possible,
but nothing for it is implemented so far.
>
>> + case OP_31_XOP_DCBZ:
>> + {
>> + ulong rb = vcpu->arch.gpr[get_rb(inst)];
>> + ulong ra = 0;
>> + ulong addr;
>> + u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
>> +
>> + if (get_ra(inst))
>> + ra = vcpu->arch.gpr[get_ra(inst)];
>> +
>> + addr = (ra + rb) & ~31ULL;
>> + if (!(vcpu->arch.msr & MSR_SF))
>> + addr &= 0xffffffff;
>> +
>> + if (kvmppc_st(vcpu, addr, 32, zeros)) {
>
> DCBZ zeroes out a cache line, not 32 bytes; except on 970, where there
> are HID bits to make it work on 32 bytes only, and an extra DCBZL insn
> that always clears a full cache line (128 bytes).
Yes. We only come here when we patched the dcbz opcodes to invalid
instructions because cache line size of target == 32.
On 970 with MSR_HV = 0 we actually use the dcbz 32-bytes mode.
Admittedly though, this could be a lot more clever.
>> + switch (sprn) {
>> + case SPRN_IBAT0U ... SPRN_IBAT3L:
>> + bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2];
>> + break;
>> + case SPRN_IBAT4U ... SPRN_IBAT7L:
>> + bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT4U) / 2];
>> + break;
>> + case SPRN_DBAT0U ... SPRN_DBAT3L:
>> + bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2];
>> + break;
>> + case SPRN_DBAT4U ... SPRN_DBAT7L:
>> + bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT4U) / 2];
>> + break;
>
> Do xBAT4..7 have the same SPR numbers on all CPUs? They are CPU-
> specific
> SPRs, after all. Some CPUs have only six, some only four, some
> none, btw.
For now only Linux runs which only uses the first 3(?) IIRC. But yes,
it's probably worth looking into at one point or the other.
>
>> + case SPRN_HID0:
>> + to_book3s(vcpu)->hid[0] = vcpu->arch.gpr[rs];
>> + break;
>> + case SPRN_HID1:
>> + to_book3s(vcpu)->hid[1] = vcpu->arch.gpr[rs];
>> + break;
>> + case SPRN_HID2:
>> + to_book3s(vcpu)->hid[2] = vcpu->arch.gpr[rs];
>> + break;
>> + case SPRN_HID4:
>> + to_book3s(vcpu)->hid[4] = vcpu->arch.gpr[rs];
>> + break;
>> + case SPRN_HID5:
>> + to_book3s(vcpu)->hid[5] = vcpu->arch.gpr[rs];
>
> HIDs are different per CPU; and worse, different CPUs have different
> registers (SPR #s) for the same register name!
Sigh :-(
>> + /* guest HID5 set can change is_dcbz32 */
>> + if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
>> + (mfmsr() & MSR_HV))
>> + vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
>> + break;
>
> Wait, does this mean you allow other HID writes when MSR[HV] isn't
> set? All HIDs (and many other SPRs) cannot be read or written in
> supervisor mode.
When we're running in MSR_HV=0 mode on a 970 we can use the 32 byte
dcbz HID flag. So all we need to do is tell our entry/exit code to set
this bit.
If we're on 970 on a hypervisor or on a non-970 though we can't use
the HID5 bit, so we need to binary patch the opcodes.
So in order to emulate real 970 behavior, we need to be able to
emulate that HID5 bit too! That's what this chunk of code does - it
basically sets us in dcbz32 mode when allowed on 970 guests.
Alex
^ permalink raw reply
* Re: mpc8548 does not make use of DMA when doing memory copy?
From: Micha Nelissen @ 2009-11-03 8:40 UTC (permalink / raw)
To: hank peng, linuxppc-dev
In-Reply-To: <389deec70911021635v6e12a976t9e20fb5f12d8987b@mail.gmail.com>
hank peng wrote:
> I remember normal memory copy can also be done (chosen by user) by DMA
> engine on IOP80331(Intel embedded cpu, xscale arch), so why ppc
> platform didn't make use of DMA doing memory copy, I think it can
> increase performance, please correct me if I am wrong!
AFAIK the DMA engine has only an asynchronous mode (not very smart
IMHO). This means you always have the overhead of context switch +
interrupt + context switch, so the transfer has to be quite large for
this to pay off.
Micha
^ permalink raw reply
* Re: [PATCH 0/8] Fix 8xx MMU/TLB
From: Joakim Tjernlund @ 2009-11-03 13:32 UTC (permalink / raw)
To: Scott Wood; +Cc: Rex Feany, linuxppc-dev@ozlabs.org
In-Reply-To: <20091030173749.GA855@loki.buserror.net>
Scott Wood <scottwood@freescale.com> wrote on 30/10/2009 18:37:49:
>
> On Fri, Oct 30, 2009 at 12:16:07PM -0500, Scott Wood wrote:
> > On Sat, Oct 17, 2009 at 02:01:38PM +0200, Joakim Tjernlund wrote:
> > > + mfspr r10, SPRN_SRR0
> > > DO_8xx_CPU6(0x3780, r3)
> > > mtspr SPRN_MD_EPN, r10
> > > mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */
> > > - lwz r11, 0(r11) /* Get the level 1 entry */
> > > + cmplwi cr0, r11, 0x0800
> > > + blt- 3f /* Branch if user space */
> > > + lis r11, swapper_pg_dir@h
> > > + ori r11, r11, swapper_pg_dir@l
> > > + rlwimi r11, r11, 0, 2, 19
> >
> > That rlwimi is a no-op -- I think you meant to use a different register
> > here?
> >
> > > +3: lwz r11, 0(r11) /* Get the level 1 entry */
> > > DO_8xx_CPU6(0x3b80, r3)
> > > mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
> > > mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
> > > lwz r11, 0(r11) /* Get the pte */
> > > /* concat physical page address(r11) and page offset(r10) */
> > > rlwimi r11, r10, 0, 20, 31
> >
> > But r10 here contains SRR0 from above, and this is a data TLB error.
>
> Never mind that last one, forgot that you'd be wanting to load the
> instruction. :-P
>
> But the rlwimi is what's causing the machine checks. I replaced it with:
> rlwinm r11, r11, 0, 0x3ffff000
> rlwimi r11, r10, 22, 0xffc
>
> and things seem to work. You could probably replace the rlwinm by
> subtracting PAGE_OFFSET from swapper_pg_dir instead.
Just guessing here, do you mean:
lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
rlwimi r11, r10, 22, 0xffc
or
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
subis r11, r11 PAGE_OFFSET
rlwimi r11, r10, 22, 0xffc
Jocke
^ permalink raw reply
* [PATCH 10/13] mac68k: start CUDA early
From: Finn Thain @ 2009-11-03 13:46 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linuxppc-dev, linux-m68k
The valkyriefb driver needs the CUDA to work in order to set the video
mode at boot. Initialising the device earlier, and bring the m68k code
closer to the powermac code.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
arch/m68k/mac/config.c | 6 ++++
drivers/macintosh/via-cuda.c | 57 +++++++++++++++++++++++++++----------------
2 files changed, 43 insertions(+), 20 deletions(-)
Index: linux-2.6.31/arch/m68k/mac/config.c
===================================================================
--- linux-2.6.31.orig/arch/m68k/mac/config.c 2009-11-03 03:23:42.000000000 +1100
+++ linux-2.6.31/arch/m68k/mac/config.c 2009-11-03 03:23:43.000000000 +1100
@@ -23,6 +23,8 @@
#include <linux/init.h>
#include <linux/vt_kern.h>
#include <linux/platform_device.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
#define BOOTINFO_COMPAT_1_0
#include <asm/setup.h>
@@ -889,6 +891,10 @@ static void __init mac_identify(void)
oss_init();
psc_init();
baboon_init();
+
+#ifdef CONFIG_ADB_CUDA
+ find_via_cuda();
+#endif
}
static void __init mac_report_hardware(void)
Index: linux-2.6.31/drivers/macintosh/via-cuda.c
===================================================================
--- linux-2.6.31.orig/drivers/macintosh/via-cuda.c 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/drivers/macintosh/via-cuda.c 2009-11-03 03:23:43.000000000 +1100
@@ -117,7 +117,33 @@ struct adb_driver via_cuda_driver = {
};
#endif /* CONFIG_ADB */
-#ifdef CONFIG_PPC
+#ifdef CONFIG_MAC
+int __init find_via_cuda(void)
+{
+ struct adb_request req;
+ int err;
+
+ if (macintosh_config->adb_type != MAC_ADB_CUDA)
+ return 0;
+
+ via = via1;
+ cuda_state = idle;
+
+ err = cuda_init_via();
+ if (err) {
+ printk(KERN_ERR "cuda_init_via() failed\n");
+ via = NULL;
+ return 0;
+ }
+
+ /* enable autopoll */
+ cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
+ while (!req.complete)
+ cuda_poll();
+
+ return 1;
+}
+#else
int __init find_via_cuda(void)
{
struct adb_request req;
@@ -175,7 +201,7 @@ int __init find_via_cuda(void)
vias = NULL;
return 0;
}
-#endif /* CONFIG_PPC */
+#endif /* !defined CONFIG_MAC */
static int __init via_cuda_start(void)
{
@@ -184,14 +210,14 @@ static int __init via_cuda_start(void)
#ifdef CONFIG_MAC
cuda_irq = IRQ_MAC_ADB;
-#else /* CONFIG_MAC */
+#else
cuda_irq = irq_of_parse_and_map(vias, 0);
if (cuda_irq == NO_IRQ) {
printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",
vias->full_name);
return -ENODEV;
}
-#endif /* CONFIG_MAC */
+#endif
if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
@@ -216,7 +242,6 @@ cuda_probe(void)
#else
if (macintosh_config->adb_type != MAC_ADB_CUDA)
return -ENODEV;
- via = via1;
#endif
return 0;
}
@@ -224,20 +249,9 @@ cuda_probe(void)
static int __init
cuda_init(void)
{
-#ifdef CONFIG_PPC
if (via == NULL)
return -ENODEV;
return 0;
-#else
- int err = cuda_init_via();
- if (err) {
- printk(KERN_ERR "cuda_init_via() failed\n");
- return -ENODEV;
- }
- out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
-
- return via_cuda_start();
-#endif
}
#endif /* CONFIG_ADB */
@@ -430,9 +444,12 @@ cuda_poll(void)
/* cuda_interrupt only takes a normal lock, we disable
* interrupts here to avoid re-entering and thus deadlocking.
*/
- disable_irq(cuda_irq);
- cuda_interrupt(0, NULL);
- enable_irq(cuda_irq);
+ if (cuda_fully_inited) {
+ disable_irq(cuda_irq);
+ cuda_interrupt(0, NULL);
+ enable_irq(cuda_irq);
+ } else
+ cuda_interrupt(0, NULL);
}
static irqreturn_t
@@ -446,7 +463,7 @@ cuda_interrupt(int irq, void *arg)
spin_lock(&cuda_lock);
- /* On powermacs, this handler is registered for the VIA IRQ. But it uses
+ /* On powermacs, this handler is registered for the VIA IRQ. But they use
* just the shift register IRQ -- other VIA interrupt sources are disabled.
* On m68k macs, the VIA IRQ sources are dispatched individually. Unless
* we are polling, the shift register IRQ flag has already been cleared.
^ permalink raw reply
* [PATCH 3/13] pmac-zilog: cleanup
From: Finn Thain @ 2009-11-03 13:40 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linux-m68k, linuxppc-dev
Whitespace cleanups and comment typo fix.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
drivers/serial/pmac_zilog.c | 85 +++++++++++++++++++++-----------------------
drivers/serial/pmac_zilog.h | 20 +++++-----
2 files changed, 51 insertions(+), 54 deletions(-)
Index: linux-2.6.31/drivers/serial/pmac_zilog.c
===================================================================
--- linux-2.6.31.orig/drivers/serial/pmac_zilog.c 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/drivers/serial/pmac_zilog.c 2009-11-03 03:23:41.000000000 +1100
@@ -153,8 +153,8 @@ static void pmz_load_zsregs(struct uart_
write_zsreg(uap, R10, regs[R10]);
/* Set TX/RX controls sans the enable bits. */
- write_zsreg(uap, R3, regs[R3] & ~RxENABLE);
- write_zsreg(uap, R5, regs[R5] & ~TxENABLE);
+ write_zsreg(uap, R3, regs[R3] & ~RxENABLE);
+ write_zsreg(uap, R5, regs[R5] & ~TxENABLE);
/* now set R7 "prime" on ESCC */
write_zsreg(uap, R15, regs[R15] | EN85C30);
@@ -205,7 +205,7 @@ static void pmz_load_zsregs(struct uart_
*/
static void pmz_maybe_update_regs(struct uart_pmac_port *uap)
{
- if (!ZS_REGS_HELD(uap)) {
+ if (!ZS_REGS_HELD(uap)) {
if (ZS_TX_ACTIVE(uap)) {
uap->flags |= PMACZILOG_FLAG_REGS_HELD;
} else {
@@ -281,7 +281,7 @@ static struct tty_struct *pmz_receive_ch
spin_lock(&uap->port.lock);
if (swallow)
goto next_char;
- }
+ }
#endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */
/* A real serial line, record the character and status. */
@@ -317,7 +317,7 @@ static struct tty_struct *pmz_receive_ch
if (uap->port.ignore_status_mask == 0xff ||
(r1 & uap->port.ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
+ tty_insert_flip_char(tty, ch, flag);
}
if (r1 & Rx_OVR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
@@ -459,47 +459,47 @@ static irqreturn_t pmz_interrupt(int irq
uap_a = pmz_get_port_A(uap);
uap_b = uap_a->mate;
-
- spin_lock(&uap_a->port.lock);
+
+ spin_lock(&uap_a->port.lock);
r3 = read_zsreg(uap_a, R3);
#ifdef DEBUG_HARD
pmz_debug("irq, r3: %x\n", r3);
#endif
- /* Channel A */
+ /* Channel A */
tty = NULL;
- if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
+ if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
write_zsreg(uap_a, R0, RES_H_IUS);
zssync(uap_a);
- if (r3 & CHAEXT)
- pmz_status_handle(uap_a);
+ if (r3 & CHAEXT)
+ pmz_status_handle(uap_a);
if (r3 & CHARxIP)
tty = pmz_receive_chars(uap_a);
- if (r3 & CHATxIP)
- pmz_transmit_chars(uap_a);
- rc = IRQ_HANDLED;
- }
- spin_unlock(&uap_a->port.lock);
+ if (r3 & CHATxIP)
+ pmz_transmit_chars(uap_a);
+ rc = IRQ_HANDLED;
+ }
+ spin_unlock(&uap_a->port.lock);
if (tty != NULL)
tty_flip_buffer_push(tty);
if (uap_b->node == NULL)
goto out;
- spin_lock(&uap_b->port.lock);
+ spin_lock(&uap_b->port.lock);
tty = NULL;
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
write_zsreg(uap_b, R0, RES_H_IUS);
zssync(uap_b);
- if (r3 & CHBEXT)
- pmz_status_handle(uap_b);
- if (r3 & CHBRxIP)
- tty = pmz_receive_chars(uap_b);
- if (r3 & CHBTxIP)
- pmz_transmit_chars(uap_b);
- rc = IRQ_HANDLED;
- }
- spin_unlock(&uap_b->port.lock);
+ if (r3 & CHBEXT)
+ pmz_status_handle(uap_b);
+ if (r3 & CHBRxIP)
+ tty = pmz_receive_chars(uap_b);
+ if (r3 & CHBTxIP)
+ pmz_transmit_chars(uap_b);
+ rc = IRQ_HANDLED;
+ }
+ spin_unlock(&uap_b->port.lock);
if (tty != NULL)
tty_flip_buffer_push(tty);
@@ -707,7 +707,7 @@ static void pmz_enable_ms(struct uart_po
if (ZS_IS_ASLEEP(uap))
return;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(uap, R15, uap->curregs[R15]);
}
}
@@ -737,7 +737,7 @@ static void pmz_break_ctl(struct uart_po
if (new_reg != uap->curregs[R5]) {
uap->curregs[R5] = new_reg;
- /* NOTE: Not subject to 'transmitter active' rule. */
+ /* NOTE: Not subject to 'transmitter active' rule. */
if (ZS_IS_ASLEEP(uap))
return;
write_zsreg(uap, R5, uap->curregs[R5]);
@@ -897,7 +897,6 @@ static int __pmz_startup(struct uart_pma
/* Remember status for DCD/CTS changes */
uap->prev_status = read_zsreg(uap, R0);
-
return pwr_delay;
}
@@ -972,7 +971,7 @@ static int pmz_startup(struct uart_port
if (!ZS_IS_EXTCLK(uap))
uap->curregs[R1] |= EXT_INT_ENAB;
write_zsreg(uap, R1, uap->curregs[R1]);
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
pmz_debug("pmz: startup() done.\n");
@@ -992,7 +991,7 @@ static void pmz_shutdown(struct uart_por
mutex_lock(&pmz_irq_mutex);
/* Release interrupt handler */
- free_irq(uap->port.irq, uap);
+ free_irq(uap->port.irq, uap);
spin_lock_irqsave(&port->lock, flags);
@@ -1040,7 +1039,6 @@ static void pmz_convert_to_zs(struct uar
{
int brg;
-
/* Switch to external clocking for IrDA high clock rates. That
* code could be re-used for Midi interfaces with different
* multipliers
@@ -1212,12 +1210,12 @@ static void pmz_irda_setup(struct uart_p
uap->curregs[R5] |= DTR;
write_zsreg(uap, R5, uap->curregs[R5]);
zssync(uap);
- mdelay(1);
+ mdelay(1);
/* Switch SCC to 19200 */
pmz_convert_to_zs(uap, CS8, 0, 19200);
pmz_load_zsregs(uap, uap->curregs);
- mdelay(1);
+ mdelay(1);
/* Write get_version command byte */
write_zsdata(uap, 1);
@@ -1452,7 +1450,7 @@ static int __init pmz_init_port(struct u
return -ENODEV;
uap->port.mapbase = r_ports.start;
uap->port.membase = ioremap(uap->port.mapbase, 0x1000);
-
+
uap->control_reg = uap->port.membase;
uap->data_reg = uap->control_reg + 0x10;
@@ -1579,7 +1577,7 @@ static void pmz_dispose_port(struct uart
}
/*
- * Called upon match with an escc node in the devive-tree.
+ * Called upon match with an escc node in the device-tree.
*/
static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match)
{
@@ -1801,7 +1799,7 @@ static int __init pmz_probe(void)
pmz_ports[count].node = node_a;
pmz_ports[count+1].node = node_b;
pmz_ports[count].port.line = count;
- pmz_ports[count+1].port.line = count+1;
+ pmz_ports[count+1].port.line = count+1;
/*
* Setup the ports for real
@@ -1888,23 +1886,22 @@ err_out:
static struct of_device_id pmz_match[] =
{
{
- .name = "ch-a",
+ .name = "ch-a",
},
{
- .name = "ch-b",
+ .name = "ch-b",
},
{},
};
MODULE_DEVICE_TABLE (of, pmz_match);
-static struct macio_driver pmz_driver =
-{
+static struct macio_driver pmz_driver = {
.name = "pmac_zilog",
.match_table = pmz_match,
.probe = pmz_attach,
.remove = pmz_detach,
.suspend = pmz_suspend,
- .resume = pmz_resume,
+ .resume = pmz_resume,
};
static int __init init_pmz(void)
@@ -1941,7 +1938,7 @@ static int __init init_pmz(void)
pmz_dispose_port(&pmz_ports[i]);
return rc;
}
-
+
/*
* Then we register the macio driver itself
*/
@@ -2023,7 +2020,7 @@ static int __init pmz_console_setup(stru
if (machine_is_compatible("RackMac1,1")
|| machine_is_compatible("RackMac1,2")
|| machine_is_compatible("MacRISC4"))
- baud = 57600;
+ baud = 57600;
/*
* Check whether an invalid uart number has been specified, and
Index: linux-2.6.31/drivers/serial/pmac_zilog.h
===================================================================
--- linux-2.6.31.orig/drivers/serial/pmac_zilog.h 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/drivers/serial/pmac_zilog.h 2009-11-03 03:23:41.000000000 +1100
@@ -1,7 +1,7 @@
#ifndef __PMAC_ZILOG_H__
#define __PMAC_ZILOG_H__
-#define pmz_debug(fmt,arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
+#define pmz_debug(fmt, arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
/*
* At most 2 ESCCs with 2 ports each
@@ -113,7 +113,7 @@ static inline void zssync(struct uart_pm
#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
-#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */
+#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */
/* The Zilog register set */
@@ -171,7 +171,7 @@ static inline void zssync(struct uart_pm
/* Write Register 3 */
-#define RxENABLE 0x1 /* Rx Enable */
+#define RxENABLE 0x1 /* Rx Enable */
#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
@@ -185,7 +185,7 @@ static inline void zssync(struct uart_pm
/* Write Register 4 */
-#define PAR_ENAB 0x1 /* Parity Enable */
+#define PAR_ENAB 0x1 /* Parity Enable */
#define PAR_EVEN 0x2 /* Parity Even/Odd* */
#define SYNC_ENAB 0 /* Sync Modes Enable */
@@ -210,7 +210,7 @@ static inline void zssync(struct uart_pm
#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
#define RTS 0x2 /* RTS */
#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
-#define TxENABLE 0x8 /* Tx Enable */
+#define TxENABLE 0x8 /* Tx Enable */
#define SND_BRK 0x10 /* Send Break */
#define Tx5 0x0 /* Tx 5 bits (or less)/character */
#define Tx7 0x20 /* Tx 7 bits/character */
@@ -372,11 +372,11 @@ static inline void zssync(struct uart_pm
#define ZS_TX_ACTIVE(UP) ((UP)->flags & PMACZILOG_FLAG_TX_ACTIVE)
#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & PMACZILOG_FLAG_MODEM_STATUS)
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
-#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
+#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
-#define ZS_IS_ASLEEP(UP) ((UP)->flags & PMACZILOG_FLAG_IS_ASLEEP)
-#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
-#define ZS_IS_IRQ_ON(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRQ_ON)
-#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
+#define ZS_IS_ASLEEP(UP) ((UP)->flags & PMACZILOG_FLAG_IS_ASLEEP)
+#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
+#define ZS_IS_IRQ_ON(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRQ_ON)
+#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
#endif /* __PMAC_ZILOG_H__ */
^ permalink raw reply
* [PATCH 4/13] pmac-zilog, mac68k: replace mac68k SCC code with platform device
From: Finn Thain @ 2009-11-03 13:40 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linux-m68k, linuxppc-dev
Remove the old 68k Mac serial port code and a lot of related cruft. Add
platform driver support to the pmac-zilog driver, putting the powermac-
specific bits inside #ifdef CONFIG_PPC_PMAC. Add new platform devices to
mac68k.
Tested on a beige G3 PowerMac and a variety of 68k Macs.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
arch/m68k/Kconfig | 6
arch/m68k/configs/mac_defconfig | 7
arch/m68k/configs/multi_defconfig | 6
arch/m68k/include/asm/machw.h | 25 --
arch/m68k/include/asm/macints.h | 22 --
arch/m68k/mac/Makefile | 2
arch/m68k/mac/config.c | 51 +++++
arch/m68k/mac/debug.c | 365 --------------------------------------
arch/m68k/mac/macints.c | 101 +---------
arch/m68k/mac/oss.c | 20 --
arch/m68k/mac/via.c | 7
drivers/serial/Kconfig | 12 -
drivers/serial/pmac_zilog.c | 159 ++++++++++++++--
drivers/serial/pmac_zilog.h | 14 +
14 files changed, 249 insertions(+), 548 deletions(-)
Index: linux-2.6.31/drivers/serial/Kconfig
===================================================================
--- linux-2.6.31.orig/drivers/serial/Kconfig 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/drivers/serial/Kconfig 2009-11-03 03:23:41.000000000 +1100
@@ -1079,12 +1079,12 @@ config SERIAL_68360
default y
config SERIAL_PMACZILOG
- tristate "PowerMac z85c30 ESCC support"
- depends on PPC_OF && PPC_PMAC
+ tristate "Mac or PowerMac z85c30 ESCC support"
+ depends on (M68K && MAC) || (PPC_OF && PPC_PMAC)
select SERIAL_CORE
help
This driver supports the Zilog z85C30 serial ports found on
- PowerMac machines.
+ (Power)Mac machines.
Say Y or M if you want to be able to these serial ports.
config SERIAL_PMACZILOG_TTYS
@@ -1109,16 +1109,16 @@ config SERIAL_PMACZILOG_TTYS
unable to use the 8250 module for PCMCIA or other 16C550-style
UARTs.
- Say N unless you need the z85c30 ports on your powermac
+ Say N unless you need the z85c30 ports on your (Power)Mac
to appear as /dev/ttySn.
config SERIAL_PMACZILOG_CONSOLE
- bool "Console on PowerMac z85c30 serial port"
+ bool "Console on Mac or PowerMac z85c30 serial port"
depends on SERIAL_PMACZILOG=y
select SERIAL_CORE_CONSOLE
help
If you would like to be able to use the z85c30 serial port
- on your PowerMac as the console, you can do so by answering
+ on your (Power)Mac as the console, you can do so by answering
Y to this option.
config SERIAL_LH7A40X
Index: linux-2.6.31/arch/m68k/Kconfig
===================================================================
--- linux-2.6.31.orig/arch/m68k/Kconfig 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/Kconfig 2009-11-03 03:23:41.000000000 +1100
@@ -530,10 +530,6 @@ config GVPIOEXT_PLIP
Say Y to enable doing IP over the parallel port on your GVP
IO-Extender card, N otherwise.
-config MAC_SCC
- tristate "Macintosh serial support"
- depends on MAC
-
config MAC_HID
bool
depends on INPUT_ADBHID
@@ -589,7 +585,7 @@ config DN_SERIAL
config SERIAL_CONSOLE
bool "Support for serial port console"
- depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
+ depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
---help---
If you say Y here, it will be possible to use a serial port as the
system console (the system console is the device which receives all
Index: linux-2.6.31/arch/m68k/configs/mac_defconfig
===================================================================
--- linux-2.6.31.orig/arch/m68k/configs/mac_defconfig 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/configs/mac_defconfig 2009-11-03 03:23:41.000000000 +1100
@@ -701,6 +701,11 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_PMACZILOG=y
+CONFIG_SERIAL_PMACZILOG_TTYS=y
+CONFIG_SERIAL_PMACZILOG_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
@@ -834,9 +839,7 @@ CONFIG_HIDRAW=y
#
# Character devices
#
-CONFIG_MAC_SCC=y
CONFIG_MAC_HID=y
-CONFIG_SERIAL_CONSOLE=y
#
# File systems
Index: linux-2.6.31/arch/m68k/configs/multi_defconfig
===================================================================
--- linux-2.6.31.orig/arch/m68k/configs/multi_defconfig 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/configs/multi_defconfig 2009-11-03 03:23:41.000000000 +1100
@@ -822,6 +822,11 @@ CONFIG_A2232=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_PMACZILOG=y
+CONFIG_SERIAL_PMACZILOG_TTYS=y
+CONFIG_SERIAL_PMACZILOG_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
@@ -982,7 +987,6 @@ CONFIG_ATARI_MIDI=y
CONFIG_ATARI_DSP56K=m
CONFIG_AMIGA_BUILTIN_SERIAL=y
CONFIG_MULTIFACE_III_TTY=m
-CONFIG_MAC_SCC=y
CONFIG_MAC_HID=y
CONFIG_MVME147_SCC=y
CONFIG_SERIAL167=y
Index: linux-2.6.31/drivers/serial/pmac_zilog.c
===================================================================
--- linux-2.6.31.orig/drivers/serial/pmac_zilog.c 2009-11-03 03:23:41.000000000 +1100
+++ linux-2.6.31/drivers/serial/pmac_zilog.c 2009-11-03 03:23:41.000000000 +1100
@@ -63,11 +63,18 @@
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/irq.h>
+
+#ifdef CONFIG_PPC_PMAC
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
#include <asm/macio.h>
+#else
+#include <linux/platform_device.h>
+#include <asm/macints.h>
+#define machine_is_compatible(x) (0)
+#endif
#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -83,11 +90,9 @@
static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
-MODULE_DESCRIPTION("Driver for the PowerMac serial ports.");
+MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports.");
MODULE_LICENSE("GPL");
-#define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg)
-
#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
#define PMACZILOG_MAJOR TTY_MAJOR
#define PMACZILOG_MINOR 64
@@ -341,7 +346,7 @@ static struct tty_struct *pmz_receive_ch
uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
write_zsreg(uap, R1, uap->curregs[R1]);
zssync(uap);
- dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n");
+ pmz_error("pmz: rx irq flood !\n");
return tty;
}
@@ -746,6 +751,8 @@ static void pmz_break_ctl(struct uart_po
spin_unlock_irqrestore(&port->lock, flags);
}
+#ifdef CONFIG_PPC_PMAC
+
/*
* Turn power on or off to the SCC and associated stuff
* (port drivers, modem, IR port, etc.)
@@ -781,6 +788,15 @@ static int pmz_set_scc_power(struct uart
return delay;
}
+#else
+
+static int pmz_set_scc_power(struct uart_pmac_port *uap, int state)
+{
+ return 0;
+}
+
+#endif /* !CONFIG_PPC_PMAC */
+
/*
* FixZeroBug....Works around a bug in the SCC receving channel.
* Inspired from Darwin code, 15 Sept. 2000 -DanM
@@ -943,9 +959,9 @@ static int pmz_startup(struct uart_port
}
pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
- if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, "PowerMac Zilog", uap)) {
- dev_err(&uap->dev->ofdev.dev,
- "Unable to register zs interrupt handler.\n");
+ if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED,
+ "SCC", uap)) {
+ pmz_error("Unable to register zs interrupt handler.\n");
pmz_set_scc_power(uap, 0);
mutex_unlock(&pmz_irq_mutex);
return -ENXIO;
@@ -1185,7 +1201,7 @@ static void pmz_irda_setup(struct uart_p
while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0
|| (read_zsreg(uap, R1) & ALL_SNT) == 0) {
if (--t <= 0) {
- dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n");
+ pmz_error("transmitter didn't drain\n");
return;
}
udelay(10);
@@ -1201,7 +1217,7 @@ static void pmz_irda_setup(struct uart_p
read_zsdata(uap);
mdelay(10);
if (--t <= 0) {
- dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n");
+ pmz_error("receiver didn't drain\n");
return;
}
}
@@ -1222,8 +1238,7 @@ static void pmz_irda_setup(struct uart_p
t = 5000;
while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
if (--t <= 0) {
- dev_err(&uap->dev->ofdev.dev,
- "irda_setup timed out on get_version byte\n");
+ pmz_error("irda_setup timed out on get_version byte\n");
goto out;
}
udelay(10);
@@ -1231,8 +1246,7 @@ static void pmz_irda_setup(struct uart_p
version = read_zsdata(uap);
if (version < 4) {
- dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n",
- version);
+ pmz_info("IrDA: dongle version %d not supported\n", version);
goto out;
}
@@ -1241,19 +1255,17 @@ static void pmz_irda_setup(struct uart_p
t = 5000;
while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
if (--t <= 0) {
- dev_err(&uap->dev->ofdev.dev,
- "irda_setup timed out on speed mode byte\n");
+ pmz_error("irda_setup timed out on speed mode byte\n");
goto out;
}
udelay(10);
}
t = read_zsdata(uap);
if (t != cmdbyte)
- dev_err(&uap->dev->ofdev.dev,
- "irda_setup speed mode byte = %x (%x)\n", t, cmdbyte);
+ pmz_error("irda_setup speed mode byte = %x (%x)\n", t, cmdbyte);
- dev_info(&uap->dev->ofdev.dev, "IrDA setup for %ld bps, dongle version: %d\n",
- *baud, version);
+ pmz_info("IrDA setup for %ld bps, dongle version: %d\n",
+ *baud, version);
(void)read_zsdata(uap);
(void)read_zsdata(uap);
@@ -1402,7 +1414,7 @@ static void pmz_poll_put_char(struct uar
write_zsdata(uap, c);
}
-#endif
+#endif /* CONFIG_CONSOLE_POLL */
static struct uart_ops pmz_pops = {
.tx_empty = pmz_tx_empty,
@@ -1427,6 +1439,8 @@ static struct uart_ops pmz_pops = {
#endif
};
+#ifdef CONFIG_PPC_PMAC
+
/*
* Setup one port structure after probing, HW is down at this point,
* Unlike sunzilog, we don't need to pre-init the spinlock as we don't
@@ -1823,6 +1837,88 @@ next:
return 0;
}
+#else
+
+extern struct platform_device scc_a_pdev, scc_b_pdev;
+
+static int __init pmz_init_port(struct uart_pmac_port *uap)
+{
+ struct resource *r_ports;
+ int irq;
+
+ r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(uap->node, 0);
+ if (!r_ports || !irq)
+ return -ENODEV;
+
+ uap->port.mapbase = r_ports->start;
+ uap->port.membase = (unsigned char __iomem *) r_ports->start;
+ uap->port.iotype = UPIO_MEM;
+ uap->port.irq = irq;
+ uap->port.uartclk = ZS_CLOCK;
+ uap->port.fifosize = 1;
+ uap->port.ops = &pmz_pops;
+ uap->port.type = PORT_PMAC_ZILOG;
+ uap->port.flags = 0;
+
+ uap->control_reg = uap->port.membase;
+ uap->data_reg = uap->control_reg + 4;
+ uap->port_type = 0;
+
+ pmz_convert_to_zs(uap, CS8, 0, 9600);
+
+ return 0;
+}
+
+static int __init pmz_probe(void)
+{
+ int err;
+
+ pmz_ports_count = 0;
+
+ pmz_ports[0].mate = &pmz_ports[1];
+ pmz_ports[0].port.line = 0;
+ pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
+ pmz_ports[0].node = &scc_a_pdev;
+ err = pmz_init_port(&pmz_ports[0]);
+ if (err)
+ return err;
+ pmz_ports_count++;
+
+ pmz_ports[1].mate = &pmz_ports[0];
+ pmz_ports[1].port.line = 1;
+ pmz_ports[1].flags = 0;
+ pmz_ports[1].node = &scc_b_pdev;
+ err = pmz_init_port(&pmz_ports[1]);
+ if (err)
+ return err;
+ pmz_ports_count++;
+
+ return 0;
+}
+
+static void pmz_dispose_port(struct uart_pmac_port *uap)
+{
+ memset(uap, 0, sizeof(struct uart_pmac_port));
+}
+
+static int pmz_attach(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < pmz_ports_count; i++)
+ if (pmz_ports[i].node == pdev)
+ return 0;
+ return -ENODEV;
+}
+
+static int pmz_detach(struct platform_device *pdev)
+{
+ return 0;
+}
+
+#endif /* !CONFIG_PPC_PMAC */
+
#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
static void pmz_console_write(struct console *con, const char *s, unsigned int count);
@@ -1883,6 +1979,8 @@ err_out:
return rc;
}
+#ifdef CONFIG_PPC_PMAC
+
static struct of_device_id pmz_match[] =
{
{
@@ -1904,6 +2002,19 @@ static struct macio_driver pmz_driver =
.resume = pmz_resume,
};
+#else
+
+static struct platform_driver pmz_driver = {
+ .probe = pmz_attach,
+ .remove = __devexit_p(pmz_detach),
+ .driver = {
+ .name = "scc",
+ .owner = THIS_MODULE,
+ },
+};
+
+#endif /* !CONFIG_PPC_PMAC */
+
static int __init init_pmz(void)
{
int rc, i;
@@ -1942,15 +2053,23 @@ static int __init init_pmz(void)
/*
* Then we register the macio driver itself
*/
+#ifdef CONFIG_PPC_PMAC
return macio_register_driver(&pmz_driver);
+#else
+ return platform_driver_register(&pmz_driver);
+#endif
}
static void __exit exit_pmz(void)
{
int i;
+#ifdef CONFIG_PPC_PMAC
/* Get rid of macio-driver (detach from macio) */
macio_unregister_driver(&pmz_driver);
+#else
+ platform_driver_unregister(&pmz_driver);
+#endif
for (i = 0; i < pmz_ports_count; i++) {
struct uart_pmac_port *uport = &pmz_ports[i];
Index: linux-2.6.31/drivers/serial/pmac_zilog.h
===================================================================
--- linux-2.6.31.orig/drivers/serial/pmac_zilog.h 2009-11-03 03:23:41.000000000 +1100
+++ linux-2.6.31/drivers/serial/pmac_zilog.h 2009-11-03 03:23:41.000000000 +1100
@@ -1,7 +1,15 @@
#ifndef __PMAC_ZILOG_H__
#define __PMAC_ZILOG_H__
+#ifdef CONFIG_PPC_PMAC
#define pmz_debug(fmt, arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
+#define pmz_error(fmt, arg...) dev_err(&uap->dev->ofdev.dev, fmt, ## arg)
+#define pmz_info(fmt, arg...) dev_info(&uap->dev->ofdev.dev, fmt, ## arg)
+#else
+#define pmz_debug(fmt, arg...) do { } while (0)
+#define pmz_error(fmt, arg...) printk(KERN_ERR fmt, ## arg)
+#define pmz_info(fmt, arg...) printk(KERN_INFO fmt, ## arg)
+#endif
/*
* At most 2 ESCCs with 2 ports each
@@ -17,6 +25,7 @@ struct uart_pmac_port {
struct uart_port port;
struct uart_pmac_port *mate;
+#ifdef CONFIG_PPC_PMAC
/* macio_dev for the escc holding this port (maybe be null on
* early inited port)
*/
@@ -25,6 +34,9 @@ struct uart_pmac_port {
* of "escc" node (ie. ch-a or ch-b)
*/
struct device_node *node;
+#else
+ struct platform_device *node;
+#endif
/* Port type as obtained from device tree (IRDA, modem, ...) */
int port_type;
@@ -55,10 +67,12 @@ struct uart_pmac_port {
volatile u8 __iomem *control_reg;
volatile u8 __iomem *data_reg;
+#ifdef CONFIG_PPC_PMAC
unsigned int tx_dma_irq;
unsigned int rx_dma_irq;
volatile struct dbdma_regs __iomem *tx_dma_regs;
volatile struct dbdma_regs __iomem *rx_dma_regs;
+#endif
struct ktermios termios_cache;
};
Index: linux-2.6.31/arch/m68k/mac/Makefile
===================================================================
--- linux-2.6.31.orig/arch/m68k/mac/Makefile 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/mac/Makefile 2009-11-03 03:23:41.000000000 +1100
@@ -3,4 +3,4 @@
#
obj-y := config.o macints.o iop.o via.o oss.o psc.o \
- baboon.o macboing.o debug.o misc.o
+ baboon.o macboing.o misc.o
Index: linux-2.6.31/arch/m68k/mac/debug.c
===================================================================
--- linux-2.6.31.orig/arch/m68k/mac/debug.c 2009-11-03 03:23:24.000000000 +1100
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,365 +0,0 @@
-/*
- * linux/arch/m68k/mac/debug.c
- *
- * Shamelessly stolen (SCC code and general framework) from:
- *
- * linux/arch/m68k/atari/debug.c
- *
- * Atari debugging and serial console stuff
- *
- * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#define BOOTINFO_COMPAT_1_0
-#include <asm/setup.h>
-#include <asm/bootinfo.h>
-#include <asm/macints.h>
-
-extern unsigned long mac_videobase;
-extern unsigned long mac_rowbytes;
-
-extern void mac_serial_print(const char *);
-
-#define DEBUG_HEADS
-#undef DEBUG_SCREEN
-#define DEBUG_SERIAL
-
-/*
- * These two auxiliary debug functions should go away ASAP. Only usage:
- * before the console output is up (after head.S come some other crucial
- * setup routines :-) it permits writing 'data' to the screen as bit patterns
- * (good luck reading those). Helped to figure that the bootinfo contained
- * garbage data on the amount and size of memory chunks ...
- *
- * The 'pos' argument now simply means 'linefeed after print' ...
- */
-
-#ifdef DEBUG_SCREEN
-static int peng, line;
-#endif
-
-#if 0
-
-void mac_debugging_short(int pos, short num)
-{
-#ifdef DEBUG_SCREEN
- unsigned char *pengoffset;
- unsigned char *pptr;
- int i;
-#endif
-
-#ifdef DEBUG_SERIAL
- printk("debug: %d !\n", num);
-#endif
-
-#ifdef DEBUG_SCREEN
- if (!MACH_IS_MAC) {
- /* printk("debug: %d !\n", num); */
- return;
- }
-
- /* calculate current offset */
- pengoffset = (unsigned char *)mac_videobase +
- (150+line*2) * mac_rowbytes + 80 * peng;
-
- pptr = pengoffset;
-
- for (i = 0; i < 8 * sizeof(short); i++) { /* # of bits */
- /* value mask for bit i, reverse order */
- *pptr++ = (num & (1 << (8*sizeof(short)-i-1)) ? 0xFF : 0x00);
- }
-
- peng++;
-
- if (pos) {
- line++;
- peng = 0;
- }
-#endif
-}
-
-void mac_debugging_long(int pos, long addr)
-{
-#ifdef DEBUG_SCREEN
- unsigned char *pengoffset;
- unsigned char *pptr;
- int i;
-#endif
-
-#ifdef DEBUG_SERIAL
- printk("debug: #%ld !\n", addr);
-#endif
-
-#ifdef DEBUG_SCREEN
- if (!MACH_IS_MAC) {
- /* printk("debug: #%ld !\n", addr); */
- return;
- }
-
- pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
- +80*peng;
-
- pptr = pengoffset;
-
- for (i = 0; i < 8 * sizeof(long); i++) { /* # of bits */
- *pptr++ = (addr & (1 << (8*sizeof(long)-i-1)) ? 0xFF : 0x00);
- }
-
- peng++;
-
- if (pos) {
- line++;
- peng = 0;
- }
-#endif
-}
-
-#endif /* 0 */
-
-#ifdef DEBUG_SERIAL
-/*
- * TODO: serial debug code
- */
-
-struct mac_SCC {
- u_char cha_b_ctrl;
- u_char char_dummy1;
- u_char cha_a_ctrl;
- u_char char_dummy2;
- u_char cha_b_data;
- u_char char_dummy3;
- u_char cha_a_data;
-};
-
-# define scc (*((volatile struct mac_SCC*)mac_bi_data.sccbase))
-
-static int scc_port = -1;
-
-static struct console mac_console_driver = {
- .name = "debug",
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/*
- * Crude hack to get console output to the screen before the framebuffer
- * is initialized (happens a lot later in 2.1!).
- * We just use the console routines declared in head.S, this will interfere
- * with regular framebuffer console output and should be used exclusively
- * to debug kernel problems manifesting before framebuffer init (aka WSOD)
- *
- * To keep this hack from interfering with the regular console driver, either
- * deregister this driver before/on framebuffer console init, or silence this
- * function after the fbcon driver is running (will lose console messages!?).
- * To debug real early bugs, need to write a 'mac_register_console_hack()'
- * that is called from start_kernel() before setup_arch() and just registers
- * this driver if Mac.
- */
-
-static void mac_debug_console_write(struct console *co, const char *str,
- unsigned int count)
-{
- mac_serial_print(str);
-}
-
-
-
-/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
-
-#define uSEC 1
-
-static inline void mac_sccb_out(char c)
-{
- int i;
-
- do {
- for (i = uSEC; i > 0; --i)
- barrier();
- } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
- for (i = uSEC; i > 0; --i)
- barrier();
- scc.cha_b_data = c;
-}
-
-static inline void mac_scca_out(char c)
-{
- int i;
-
- do {
- for (i = uSEC; i > 0; --i)
- barrier();
- } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
- for (i = uSEC; i > 0; --i)
- barrier();
- scc.cha_a_data = c;
-}
-
-static void mac_sccb_console_write(struct console *co, const char *str,
- unsigned int count)
-{
- while (count--) {
- if (*str == '\n')
- mac_sccb_out('\r');
- mac_sccb_out(*str++);
- }
-}
-
-static void mac_scca_console_write(struct console *co, const char *str,
- unsigned int count)
-{
- while (count--) {
- if (*str == '\n')
- mac_scca_out('\r');
- mac_scca_out(*str++);
- }
-}
-
-
-/* The following two functions do a quick'n'dirty initialization of the MFP or
- * SCC serial ports. They're used by the debugging interface, kgdb, and the
- * serial console code. */
-#define SCCB_WRITE(reg,val) \
- do { \
- int i; \
- scc.cha_b_ctrl = (reg); \
- for (i = uSEC; i > 0; --i) \
- barrier(); \
- scc.cha_b_ctrl = (val); \
- for (i = uSEC; i > 0; --i) \
- barrier(); \
- } while(0)
-
-#define SCCA_WRITE(reg,val) \
- do { \
- int i; \
- scc.cha_a_ctrl = (reg); \
- for (i = uSEC; i > 0; --i) \
- barrier(); \
- scc.cha_a_ctrl = (val); \
- for (i = uSEC; i > 0; --i) \
- barrier(); \
- } while(0)
-
-/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
- * delay of ~ 60us. */
-/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
-#define LONG_DELAY() \
- do { \
- int i; \
- for (i = 60*uSEC; i > 0; --i) \
- barrier(); \
- } while(0)
-
-static void __init mac_init_scc_port(int cflag, int port)
-{
- /*
- * baud rates: 1200, 1800, 2400, 4800, 9600, 19.2k, 38.4k, 57.6k, 115.2k
- */
-
- static int clksrc_table[9] =
- /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
- { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
- static int clkmode_table[9] =
- /* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
- { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
- static int div_table[9] =
- /* reg12 (BRG low) */
- { 94, 62, 46, 22, 10, 4, 1, 0, 0 };
-
- int baud = cflag & CBAUD;
- int clksrc, clkmode, div, reg3, reg5;
-
- if (cflag & CBAUDEX)
- baud += B38400;
- if (baud < B1200 || baud > B38400+2)
- baud = B9600; /* use default 9600bps for non-implemented rates */
- baud -= B1200; /* tables starts at 1200bps */
-
- clksrc = clksrc_table[baud];
- clkmode = clkmode_table[baud];
- div = div_table[baud];
-
- reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
- reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
-
- if (port == 1) {
- (void)scc.cha_b_ctrl; /* reset reg pointer */
- SCCB_WRITE(9, 0xc0); /* reset */
- LONG_DELAY(); /* extra delay after WR9 access */
- SCCB_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
- 0x04 /* 1 stopbit */ |
- clkmode);
- SCCB_WRITE(3, reg3);
- SCCB_WRITE(5, reg5);
- SCCB_WRITE(9, 0); /* no interrupts */
- LONG_DELAY(); /* extra delay after WR9 access */
- SCCB_WRITE(10, 0); /* NRZ mode */
- SCCB_WRITE(11, clksrc); /* main clock source */
- SCCB_WRITE(12, div); /* BRG value */
- SCCB_WRITE(13, 0); /* BRG high byte */
- SCCB_WRITE(14, 1);
- SCCB_WRITE(3, reg3 | 1);
- SCCB_WRITE(5, reg5 | 8);
- } else if (port == 0) {
- (void)scc.cha_a_ctrl; /* reset reg pointer */
- SCCA_WRITE(9, 0xc0); /* reset */
- LONG_DELAY(); /* extra delay after WR9 access */
- SCCA_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
- 0x04 /* 1 stopbit */ |
- clkmode);
- SCCA_WRITE(3, reg3);
- SCCA_WRITE(5, reg5);
- SCCA_WRITE(9, 0); /* no interrupts */
- LONG_DELAY(); /* extra delay after WR9 access */
- SCCA_WRITE(10, 0); /* NRZ mode */
- SCCA_WRITE(11, clksrc); /* main clock source */
- SCCA_WRITE(12, div); /* BRG value */
- SCCA_WRITE(13, 0); /* BRG high byte */
- SCCA_WRITE(14, 1);
- SCCA_WRITE(3, reg3 | 1);
- SCCA_WRITE(5, reg5 | 8);
- }
-}
-#endif /* DEBUG_SERIAL */
-
-static int __init mac_debug_setup(char *arg)
-{
- if (!MACH_IS_MAC)
- return 0;
-
-#ifdef DEBUG_SERIAL
- if (!strcmp(arg, "ser") || !strcmp(arg, "ser1")) {
- /* Mac modem port */
- mac_init_scc_port(B9600|CS8, 0);
- mac_console_driver.write = mac_scca_console_write;
- scc_port = 0;
- } else if (!strcmp(arg, "ser2")) {
- /* Mac printer port */
- mac_init_scc_port(B9600|CS8, 1);
- mac_console_driver.write = mac_sccb_console_write;
- scc_port = 1;
- }
-#endif
-#ifdef DEBUG_HEADS
- if (!strcmp(arg, "scn") || !strcmp(arg, "con")) {
- /* display, using head.S console routines */
- mac_console_driver.write = mac_debug_console_write;
- }
-#endif
- if (mac_console_driver.write)
- register_console(&mac_console_driver);
- return 0;
-}
-
-early_param("debug", mac_debug_setup);
Index: linux-2.6.31/arch/m68k/include/asm/machw.h
===================================================================
--- linux-2.6.31.orig/arch/m68k/include/asm/machw.h 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/include/asm/machw.h 2009-11-03 03:23:41.000000000 +1100
@@ -21,29 +21,4 @@
#define VIDEOMEMSIZE (4096*1024)
#define VIDEOMEMMASK (-4096*1024)
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-#if 0
-/*
-** SCC Z8530
-*/
-
-#define MAC_SCC_BAS (0x50F04000)
-struct MAC_SCC
- {
- u_char cha_a_ctrl;
- u_char char_dummy1;
- u_char cha_a_data;
- u_char char_dummy2;
- u_char cha_b_ctrl;
- u_char char_dummy3;
- u_char cha_b_data;
- };
-# define mac_scc ((*(volatile struct SCC*)MAC_SCC_BAS))
-#endif
-
-#endif /* __ASSEMBLY__ */
-
#endif /* linux/machw.h */
Index: linux-2.6.31/arch/m68k/include/asm/macints.h
===================================================================
--- linux-2.6.31.orig/arch/m68k/include/asm/macints.h 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/include/asm/macints.h 2009-11-03 03:23:41.000000000 +1100
@@ -37,7 +37,6 @@
#define VIA1_SOURCE_BASE 8
#define VIA2_SOURCE_BASE 16
-#define MAC_SCC_SOURCE_BASE 24
#define PSC3_SOURCE_BASE 24
#define PSC4_SOURCE_BASE 32
#define PSC5_SOURCE_BASE 40
@@ -96,26 +95,12 @@
#define IRQ_PSC3_2 (26)
#define IRQ_PSC3_3 (27)
-/* Level 4 (SCC) interrupts */
-#define IRQ_SCC (32)
-#define IRQ_SCCA (33)
-#define IRQ_SCCB (34)
-#if 0 /* FIXME: are there multiple interrupt conditions on the SCC ?? */
-/* SCC interrupts */
-#define IRQ_SCCB_TX (32)
-#define IRQ_SCCB_STAT (33)
-#define IRQ_SCCB_RX (34)
-#define IRQ_SCCB_SPCOND (35)
-#define IRQ_SCCA_TX (36)
-#define IRQ_SCCA_STAT (37)
-#define IRQ_SCCA_RX (38)
-#define IRQ_SCCA_SPCOND (39)
-#endif
-
/* Level 4 (PSC, AV Macs only) interrupts */
#define IRQ_PSC4_0 (32)
#define IRQ_PSC4_1 (33)
+#define IRQ_MAC_SCC_A IRQ_PSC4_1
#define IRQ_PSC4_2 (34)
+#define IRQ_MAC_SCC_B IRQ_PSC4_2
#define IRQ_PSC4_3 (35)
#define IRQ_MAC_MACE_DMA IRQ_PSC4_3
@@ -146,6 +131,9 @@
#define IRQ_BABOON_2 (66)
#define IRQ_BABOON_3 (67)
+/* On non-PSC machines, the serial ports share an IRQ */
+#define IRQ_MAC_SCC IRQ_AUTO_4
+
#define SLOT2IRQ(x) (x + 47)
#define IRQ2SLOT(x) (x - 47)
Index: linux-2.6.31/arch/m68k/mac/macints.c
===================================================================
--- linux-2.6.31.orig/arch/m68k/mac/macints.c 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/mac/macints.c 2009-11-03 03:23:41.000000000 +1100
@@ -34,9 +34,7 @@
*
* 3 - unused (?)
*
- * 4 - SCC (slot number determined by reading RR3 on the SSC itself)
- * - slot 1: SCC channel A
- * - slot 2: SCC channel B
+ * 4 - SCC
*
* 5 - unused (?)
* [serial errors or special conditions seem to raise level 6
@@ -55,8 +53,6 @@
* - slot 5: Slot $E
*
* 4 - SCC IOP
- * - slot 1: SCC channel A
- * - slot 2: SCC channel B
*
* 5 - ISM IOP (ADB?)
*
@@ -136,13 +132,8 @@
#include <asm/irq_regs.h>
#include <asm/mac_oss.h>
-#define DEBUG_SPURIOUS
#define SHUTUP_SONIC
-/* SCC interrupt mask */
-
-static int scc_mask;
-
/*
* VIA/RBV hooks
*/
@@ -191,13 +182,6 @@ extern void baboon_irq_disable(int);
extern void baboon_irq_clear(int);
/*
- * SCC interrupt routines
- */
-
-static void scc_irq_enable(unsigned int);
-static void scc_irq_disable(unsigned int);
-
-/*
* console_loglevel determines NMI handler function
*/
@@ -221,8 +205,6 @@ void __init mac_init_IRQ(void)
#ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Setting things up...\n");
#endif
- scc_mask = 0;
-
m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
NUM_MAC_SOURCES - IRQ_USER);
/* Make sure the SONIC interrupt is cleared or things get ugly */
@@ -283,15 +265,16 @@ void mac_enable_irq(unsigned int irq)
via_irq_enable(irq);
break;
case 3:
- case 4:
case 5:
case 6:
if (psc_present)
psc_irq_enable(irq);
else if (oss_present)
oss_irq_enable(irq);
- else if (irq_src == 4)
- scc_irq_enable(irq);
+ break;
+ case 4:
+ if (psc_present)
+ psc_irq_enable(irq);
break;
case 8:
if (baboon_present)
@@ -316,15 +299,16 @@ void mac_disable_irq(unsigned int irq)
via_irq_disable(irq);
break;
case 3:
- case 4:
case 5:
case 6:
if (psc_present)
psc_irq_disable(irq);
else if (oss_present)
oss_irq_disable(irq);
- else if (irq_src == 4)
- scc_irq_disable(irq);
+ break;
+ case 4:
+ if (psc_present)
+ psc_irq_disable(irq);
break;
case 8:
if (baboon_present)
@@ -347,7 +331,6 @@ void mac_clear_irq(unsigned int irq)
via_irq_clear(irq);
break;
case 3:
- case 4:
case 5:
case 6:
if (psc_present)
@@ -355,6 +338,10 @@ void mac_clear_irq(unsigned int irq)
else if (oss_present)
oss_irq_clear(irq);
break;
+ case 4:
+ if (psc_present)
+ psc_irq_clear(irq);
+ break;
case 8:
if (baboon_present)
baboon_irq_clear(irq);
@@ -374,13 +361,17 @@ int mac_irq_pending(unsigned int irq)
else
return via_irq_pending(irq);
case 3:
- case 4:
case 5:
case 6:
if (psc_present)
return psc_irq_pending(irq);
else if (oss_present)
return oss_irq_pending(irq);
+ break;
+ case 4:
+ if (psc_present)
+ psc_irq_pending(irq);
+ break;
}
return 0;
}
@@ -448,59 +439,3 @@ irqreturn_t mac_nmi_handler(int irq, voi
in_nmi--;
return IRQ_HANDLED;
}
-
-/*
- * Simple routines for masking and unmasking
- * SCC interrupts in cases where this can't be
- * done in hardware (only the PSC can do that.)
- */
-
-static void scc_irq_enable(unsigned int irq)
-{
- int irq_idx = IRQ_IDX(irq);
-
- scc_mask |= (1 << irq_idx);
-}
-
-static void scc_irq_disable(unsigned int irq)
-{
- int irq_idx = IRQ_IDX(irq);
-
- scc_mask &= ~(1 << irq_idx);
-}
-
-/*
- * SCC master interrupt handler. We have to do a bit of magic here
- * to figure out what channel gave us the interrupt; putting this
- * here is cleaner than hacking it into drivers/char/macserial.c.
- */
-
-void mac_scc_dispatch(int irq, void *dev_id)
-{
- volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2;
- unsigned char reg;
- unsigned long flags;
-
- /* Read RR3 from the chip. Always do this on channel A */
- /* This must be an atomic operation so disable irqs. */
-
- local_irq_save(flags);
- *scc = 3;
- reg = *scc;
- local_irq_restore(flags);
-
- /* Now dispatch. Bits 0-2 are for channel B and */
- /* bits 3-5 are for channel A. We can safely */
- /* ignore the remaining bits here. */
- /* */
- /* Note that we're ignoring scc_mask for now. */
- /* If we actually mask the ints then we tend to */
- /* get hammered by very persistent SCC irqs, */
- /* and since they're autovector interrupts they */
- /* pretty much kill the system. */
-
- if (reg & 0x38)
- m68k_handle_int(IRQ_SCCA);
- if (reg & 0x07)
- m68k_handle_int(IRQ_SCCB);
-}
Index: linux-2.6.31/arch/m68k/mac/oss.c
===================================================================
--- linux-2.6.31.orig/arch/m68k/mac/oss.c 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/mac/oss.c 2009-11-03 03:23:41.000000000 +1100
@@ -33,7 +33,6 @@ static irqreturn_t oss_irq(int, void *);
static irqreturn_t oss_nubus_irq(int, void *);
extern irqreturn_t via1_irq(int, void *);
-extern irqreturn_t mac_scc_dispatch(int, void *);
/*
* Initialize the OSS
@@ -69,9 +68,6 @@ void __init oss_register_interrupts(void
if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
"scsi", (void *) oss))
pr_err("Couldn't register %s interrupt\n", "scsi");
- if (request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
- "scc", mac_scc_dispatch))
- pr_err("Couldn't register %s interrupt\n", "scc");
if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
"nubus", (void *) oss))
pr_err("Couldn't register %s interrupt\n", "nubus");
@@ -172,9 +168,7 @@ void oss_irq_enable(int irq) {
printk("oss_irq_enable(%d)\n", irq);
#endif
switch(irq) {
- case IRQ_SCC:
- case IRQ_SCCA:
- case IRQ_SCCB:
+ case IRQ_MAC_SCC:
oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC;
break;
case IRQ_MAC_ADB:
@@ -212,9 +206,7 @@ void oss_irq_disable(int irq) {
printk("oss_irq_disable(%d)\n", irq);
#endif
switch(irq) {
- case IRQ_SCC:
- case IRQ_SCCA:
- case IRQ_SCCB:
+ case IRQ_MAC_SCC:
oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_DISABLED;
break;
case IRQ_MAC_ADB:
@@ -250,9 +242,7 @@ void oss_irq_disable(int irq) {
void oss_irq_clear(int irq) {
/* FIXME: how to do this on OSS? */
switch(irq) {
- case IRQ_SCC:
- case IRQ_SCCA:
- case IRQ_SCCB:
+ case IRQ_MAC_SCC:
oss->irq_pending &= ~OSS_IP_IOPSCC;
break;
case IRQ_MAC_ADB:
@@ -280,9 +270,7 @@ void oss_irq_clear(int irq) {
int oss_irq_pending(int irq)
{
switch(irq) {
- case IRQ_SCC:
- case IRQ_SCCA:
- case IRQ_SCCB:
+ case IRQ_MAC_SCC:
return oss->irq_pending & OSS_IP_IOPSCC;
break;
case IRQ_MAC_ADB:
Index: linux-2.6.31/arch/m68k/mac/via.c
===================================================================
--- linux-2.6.31.orig/arch/m68k/mac/via.c 2009-11-03 03:23:24.000000000 +1100
+++ linux-2.6.31/arch/m68k/mac/via.c 2009-11-03 03:23:41.000000000 +1100
@@ -84,8 +84,6 @@ void via_irq_enable(int irq);
void via_irq_disable(int irq);
void via_irq_clear(int irq);
-extern irqreturn_t mac_scc_dispatch(int, void *);
-
/*
* Initialize the VIAs
*
@@ -311,11 +309,6 @@ void __init via_register_interrupts(void
if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
"via2", (void *) via2))
pr_err("Couldn't register %s interrupt\n", "via2");
- if (!psc_present) {
- if (request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
- "scc", mac_scc_dispatch))
- pr_err("Couldn't register %s interrupt\n", "scc");
- }
if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
pr_err("Couldn't register %s interrupt\n", "nubus");
Index: linux-2.6.31/arch/m68k/mac/config.c
===================================================================
--- linux-2.6.31.orig/arch/m68k/mac/config.c 2009-11-03 03:23:41.000000000 +1100
+++ linux-2.6.31/arch/m68k/mac/config.c 2009-11-03 03:23:41.000000000 +1100
@@ -792,6 +792,32 @@ static struct mac_model mac_data_table[]
}
};
+static struct resource scc_a_rsrcs[] = {
+ { .flags = IORESOURCE_MEM },
+ { .flags = IORESOURCE_IRQ },
+};
+
+static struct resource scc_b_rsrcs[] = {
+ { .flags = IORESOURCE_MEM },
+ { .flags = IORESOURCE_IRQ },
+};
+
+struct platform_device scc_a_pdev = {
+ .name = "scc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(scc_a_rsrcs),
+ .resource = scc_a_rsrcs,
+};
+EXPORT_SYMBOL(scc_a_pdev);
+
+struct platform_device scc_b_pdev = {
+ .name = "scc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(scc_b_rsrcs),
+ .resource = scc_b_rsrcs,
+};
+EXPORT_SYMBOL(scc_b_pdev);
+
static void __init mac_identify(void)
{
struct mac_model *m;
@@ -814,6 +840,24 @@ static void __init mac_identify(void)
}
}
+ /* Set up serial port resources for the console initcall. */
+
+ scc_a_rsrcs[0].start = (resource_size_t) mac_bi_data.sccbase + 2;
+ scc_a_rsrcs[0].end = scc_a_rsrcs[0].start;
+ scc_b_rsrcs[0].start = (resource_size_t) mac_bi_data.sccbase;
+ scc_b_rsrcs[0].end = scc_b_rsrcs[0].start;
+
+ switch (macintosh_config->scc_type) {
+ case MAC_SCC_PSC:
+ scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC_A;
+ scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC_B;
+ break;
+ default:
+ scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC;
+ scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC;
+ break;
+ }
+
/*
* We need to pre-init the IOPs, if any. Otherwise
* the serial console won't work if the user had
@@ -872,6 +916,13 @@ int __init mac_platform_init(void)
u8 *swim_base;
/*
+ * Serial devices
+ */
+
+ platform_device_register(&scc_a_pdev);
+ platform_device_register(&scc_b_pdev);
+
+ /*
* Floppy device
*/
^ permalink raw reply
* Re: mpc8548 does not make use of DMA when doing memory copy?
From: hank peng @ 2009-11-03 14:38 UTC (permalink / raw)
To: Micha Nelissen; +Cc: linuxppc-dev
In-Reply-To: <4AEFEC64.3070608@neli.hopto.org>
2009/11/3 Micha Nelissen <micha@neli.hopto.org>:
> hank peng wrote:
>>
>> I remember normal memory copy can also be done (chosen by user) by DMA
>> engine on IOP80331(Intel embedded cpu, xscale arch), so why ppc
>> platform didn't make use of DMA doing memory copy, I think it can
>> increase performance, please correct me if I am wrong!
>
> AFAIK the DMA engine has only an asynchronous mode (not very smart IMHO).
> This means you always have the overhead of context switch + interrupt +
> context switch, so the transfer has to be quite large for this to pay off.
>
but if the amount of data I want to copy is big enough? can we benefit
from using DMA in such case?
> Micha
>
--
The simplest is not all best but the best is surely the simplest!
^ permalink raw reply
* Re: [PATCH 0/8] Fix 8xx MMU/TLB
From: Scott Wood @ 2009-11-03 16:59 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: Rex Feany, linuxppc-dev@ozlabs.org
In-Reply-To: <OFD5642C2D.808C2FF1-ONC1257663.004A341C-C1257663.004A6C26@transmode.se>
Joakim Tjernlund wrote:
>> and things seem to work. You could probably replace the rlwinm by
>> subtracting PAGE_OFFSET from swapper_pg_dir instead.
>
> Just guessing here, do you mean:
> lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
> ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
> rlwimi r11, r10, 22, 0xffc
> or
> lis r11, swapper_pg_dir@h
> ori r11, r11, swapper_pg_dir@l
> subis r11, r11 PAGE_OFFSET
> rlwimi r11, r10, 22, 0xffc
The former.
-Scott
^ 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