Re: [PATCH]: [MPC5200] Add ATA DMA support
On Wed, Aug 13, 2008 at 7:02 AM, Grant Likely [EMAIL PROTECTED] wrote: While on this topic; have you had a chance to address the comments you received on v2 of your patch? I'm keen to get your change merged in, but there are a few more things that need to be sorted out. I'm still trying to determine whether the locking stuff is needed or not. I think ultimately it might be a bug caused by hardware problems at this end as opposed to silicon problems affecting everybody, but I won't have an answer regarding this for a while because new hardware needs to be prototyped to test out this theory. I think the patch can probably be resubmitted with the locking stuff removed, and the driver can be marked as experimental for everybody to try out: if people experience any corruption problems I'm sure they can speak up :-) Any objections? Tim ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH]: [MPC5200] Add ATA DMA support
On Wed, Aug 13, 2008 at 7:11 AM, Grant Likely [EMAIL PROTECTED] wrote: Sounds good to me. You will get more testers that way. I can pick it up for -next if everything else looks good. Here are the new patches; tested against 2.6.27-rc3. Thanks, Tim 1) ata.h has dst_pa in the wrong place (needs to match what the BestComm task microcode in bcom_ata_task.c expects); fix it. 2) The BestComm ATA task priority was changed to maximum in bestcomm_priv.h; this fixes a deadlock issue I was experiencing when heavy DMA was occuring on both the ATA and Ethernet BestComm tasks, e.g. when downloading a large file over a LAN to disk. 3) The ATA BestComm driver uses bcom_ata_bd which is bigger than bcom_bd and this causes problems because the various bcom_... functions do not dereference the correct location. I've introduced bcom_get_bd which uses bcom_task.bd_size and this fixes the problem. Signed-off-by: Tim Yamin [EMAIL PROTECTED] diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/ata.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/ata.h 2008-07-03 16:17:05.0 +0100 @@ -16,8 +16,8 @@ struct bcom_ata_bd { u32 status; - u32 dst_pa; u32 src_pa; + u32 dst_pa; }; extern struct bcom_task * diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-07-03 16:17:05.0 +0100 @@ -38,7 +38,7 @@ struct bcom_task { unsigned int flags; int irq; - struct bcom_bd *bd; + void *bd; phys_addr_t bd_pa; void **cookie; unsigned short index; @@ -140,15 +140,29 @@ bcom_queue_full(struct bcom_task *tsk) } /** + * bcom_get_bd - Get a BD from the queue + * @tsk: The BestComm task structure + * index: Index of the BD to fetch + */ +static inline struct bcom_bd +*bcom_get_bd(struct bcom_task *tsk, unsigned int index) +{ + return tsk-bd + index * tsk-bd_size; +} + +/** * bcom_buffer_done - Checks if a BestComm * @tsk: The BestComm task structure */ static inline int bcom_buffer_done(struct bcom_task *tsk) { + struct bcom_bd *bd; if (bcom_queue_empty(tsk)) return 0; - return !(tsk-bd[tsk-outdex].status BCOM_BD_READY); + + bd = bcom_get_bd(tsk, tsk-outdex); + return !(bd-status BCOM_BD_READY); } /** @@ -160,16 +174,21 @@ bcom_buffer_done(struct bcom_task *tsk) static inline struct bcom_bd * bcom_prepare_next_buffer(struct bcom_task *tsk) { - tsk-bd[tsk-index].status = 0; /* cleanup last status */ - return tsk-bd[tsk-index]; + struct bcom_bd *bd; + + bd = bcom_get_bd(tsk, tsk-index); + bd-status = 0; /* cleanup last status */ + return bd; } static inline void bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie) { + struct bcom_bd *bd = bcom_get_bd(tsk, tsk-index); + tsk-cookie[tsk-index] = cookie; mb(); /* ensure the bd is really up-to-date */ - tsk-bd[tsk-index].status |= BCOM_BD_READY; + bd-status |= BCOM_BD_READY; tsk-index = _bcom_next_index(tsk); if (tsk-flags BCOM_FLAGS_ENABLE_TASK) bcom_enable(tsk); @@ -179,10 +198,12 @@ static inline void * bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd) { void *cookie = tsk-cookie[tsk-outdex]; + struct bcom_bd *bd = bcom_get_bd(tsk, tsk-outdex); + if (p_status) - *p_status = tsk-bd[tsk-outdex].status; + *p_status = bd-status; if (p_bd) - *p_bd = tsk-bd[tsk-outdex]; + *p_bd = bd; tsk-outdex = _bcom_next_outdex(tsk); return cookie; } diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h 2008-07-03 16:17:05.0 +0100 @@ -198,8 +198,8 @@ struct bcom_task_header { #define BCOM_IPR_SCTMR_1 2 #define BCOM_IPR_FEC_RX 6 #define BCOM_IPR_FEC_TX 5 -#define BCOM_IPR_ATA_RX 4 -#define BCOM_IPR_ATA_TX 3 +#define BCOM_IPR_ATA_RX 7 +#define BCOM_IPR_ATA_TX 7 #define BCOM_IPR_SCPCI_RX 2 #define BCOM_IPR_SCPCI_TX 2 #define BCOM_IPR_PSC3_RX 2 This patch adds MDMA/UDMA support (using BestComm for DMA) on the MPC5200 platform. Patch requires the ATA BestComm fixes to function properly. Based heavily on previous work by Freescale (Bernard Kuhn, John Rigby) and Domen Puncer. Using a SanDisk Extreme IV CF card I get read speeds of approximately 26.70 MB/sec. Comments and testing would of course be very welcome. Thanks, Signed-off-by: Tim Yamin [EMAIL PROTECTED] diff -urp linux-2.6.27-rc3/arch/powerpc/sysdev/bestcomm/bestcomm.c linux-2.6.27-rc3-ata/arch/powerpc/sysdev/bestcomm/bestcomm.c
Re: [PATCH]: [MPC5200] Add ATA DMA support
On Tue, Aug 12, 2008 at 6:30 PM, Daniel Schnell [EMAIL PROTECTED] wrote: Hi Tim, Continuing the discussion on the mailing list ... Looking at the original patch I don't undestand why you had to duplicate the bestcomm data structures and functions. The only apparent difference is that you have a minimal data length of 2 bytes instead of 1. Does this make any difference as the bd_size will be filled with the correct length value anyway ? The new version of the patch does this the correct way. I just haven't back ported this to the 2.6.24 version that I sent you. Tim ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH]: [MPC5200] Add ATA DMA support
On Wed, Aug 6, 2008 at 12:58 PM, Daniel Schnell [EMAIL PROTECTED] wrote: Hi, Sorry for testing this patch so late, but I get these if I apply your patch to 2.6.24.7 and use it with my Sandisk Extreme IV 4GB card: Hi, What board are you using? DMA requires a few more signals to be routed through correctly to the CF card slot so maybe that's your problem... Tim ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH]: [MPC5200] (v2) Add ATA DMA support
On Wed, Jul 2, 2008 at 6:30 PM, Grant Likely [EMAIL PROTECTED] wrote: I know that only ATA uses this; but it is nice to have fixes to things that are obviously wrong in existing code to be split into their own patches. That way, even if the ATA patch gets backed out, the bug fix will remain. Ok, so I've split the patch up into two pieces now... +static void +mpc52xx_bmdma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc-ap; + struct mpc52xx_ata_priv *priv = ap-host-private_data; + + /* LocalBus lock */ + while (test_and_set_bit(0, pata_mpc52xx_ata_dma_lock) != 0) + ; Need to be able to bail on timeout. A deadlock can't occur within the PATA driver because you won't have two DMA requests happening at once, so there is no point in adding a timeout. And even if you do have a timeout, you'd have to drop the I/O request somehow, so it's not really a good idea. If anything else needs to touch the DMA lock, it should do so in a sensible fashion... Thanks, Tim 1) ata.h has dst_pa in the wrong place (needs to match what the BestComm task microcode in bcom_ata_task.c expects); fix it. 2) The BestComm ATA task priority was changed to maximum in bestcomm_priv.h; this fixes a deadlock issue I was experiencing when heavy DMA was occuring on both the ATA and Ethernet BestComm tasks, e.g. when downloading a large file over a LAN to disk. 3) The ATA BestComm driver uses bcom_ata_bd which is bigger than bcom_bd and this causes problems because the various bcom_... functions do not dereference the correct location. I've introduced bcom_get_bd which uses bcom_task.bd_size and this fixes the problem. Signed-off-by: Tim Yamin [EMAIL PROTECTED] diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/ata.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/ata.h 2008-07-03 16:17:05.0 +0100 @@ -16,8 +16,8 @@ struct bcom_ata_bd { u32 status; - u32 dst_pa; u32 src_pa; + u32 dst_pa; }; extern struct bcom_task * diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-07-03 16:17:05.0 +0100 @@ -38,7 +38,7 @@ struct bcom_task { unsigned int flags; int irq; - struct bcom_bd *bd; + void *bd; phys_addr_t bd_pa; void **cookie; unsigned short index; @@ -140,15 +140,29 @@ bcom_queue_full(struct bcom_task *tsk) } /** + * bcom_get_bd - Get a BD from the queue + * @tsk: The BestComm task structure + * index: Index of the BD to fetch + */ +static inline struct bcom_bd +*bcom_get_bd(struct bcom_task *tsk, unsigned int index) +{ + return tsk-bd + index * tsk-bd_size; +} + +/** * bcom_buffer_done - Checks if a BestComm * @tsk: The BestComm task structure */ static inline int bcom_buffer_done(struct bcom_task *tsk) { + struct bcom_bd *bd; if (bcom_queue_empty(tsk)) return 0; - return !(tsk-bd[tsk-outdex].status BCOM_BD_READY); + + bd = bcom_get_bd(tsk, tsk-outdex); + return !(bd-status BCOM_BD_READY); } /** @@ -160,16 +174,21 @@ bcom_buffer_done(struct bcom_task *tsk) static inline struct bcom_bd * bcom_prepare_next_buffer(struct bcom_task *tsk) { - tsk-bd[tsk-index].status = 0; /* cleanup last status */ - return tsk-bd[tsk-index]; + struct bcom_bd *bd; + + bd = bcom_get_bd(tsk, tsk-index); + bd-status = 0; /* cleanup last status */ + return bd; } static inline void bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie) { + struct bcom_bd *bd = bcom_get_bd(tsk, tsk-index); + tsk-cookie[tsk-index] = cookie; mb(); /* ensure the bd is really up-to-date */ - tsk-bd[tsk-index].status |= BCOM_BD_READY; + bd-status |= BCOM_BD_READY; tsk-index = _bcom_next_index(tsk); if (tsk-flags BCOM_FLAGS_ENABLE_TASK) bcom_enable(tsk); @@ -179,10 +198,12 @@ static inline void * bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd) { void *cookie = tsk-cookie[tsk-outdex]; + struct bcom_bd *bd = bcom_get_bd(tsk, tsk-outdex); + if (p_status) - *p_status = tsk-bd[tsk-outdex].status; + *p_status = bd-status; if (p_bd) - *p_bd = tsk-bd[tsk-outdex]; + *p_bd = bd; tsk-outdex = _bcom_next_outdex(tsk); return cookie; } diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h 2008-07-03 16:17:05.0 +0100 @@ -198,8 +198,8 @@ struct bcom_task_header { #define BCOM_IPR_SCTMR_1 2 #define BCOM_IPR_FEC_RX 6 #define
Re: [PATCH] powerpc/mpc5200: Fix lite5200b suspend/resume
Hi Grant, This patch works fine for me. Cheers, Tim On Tue, Jul 1, 2008 at 10:12 PM, Grant Likely [EMAIL PROTECTED] wrote: From: Tim Yamin [EMAIL PROTECTED] Suspend/resume (echo mem /sys/power/state) does not work with vanilla kernels -- the system does not suspend correctly and just hangs. This patch fixes this so suspend/resume works: 1) of_iomap does not map the whole 0xC000 of the MPC5200 immr so saving registers does not work. 2) PCI registers need to be saved and restored. Signed-off-by: Tim Yamin [EMAIL PROTECTED] Signed-off-by: Grant Likely [EMAIL PROTECTED] --- Tim, please test this version. I fixed a couple of bugs and want to make sure I haven't broken anything. Once you ack it I'll ask Paul to pull it into 2.6.26. g. arch/powerpc/platforms/52xx/lite5200_pm.c | 14 +- 1 files changed, 13 insertions(+), 1 deletions(-) diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c index 41c7fd9..fe92e65 100644 --- a/arch/powerpc/platforms/52xx/lite5200_pm.c +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c @@ -14,6 +14,7 @@ static struct mpc52xx_sdma __iomem *bes; static struct mpc52xx_xlb __iomem *xlb; static struct mpc52xx_gpio __iomem *gps; static struct mpc52xx_gpio_wkup __iomem *gpw; +static void __iomem *pci; static void __iomem *sram; static const int sram_size = 0x4000; /* 16 kBytes */ static void __iomem *mbar; @@ -50,6 +51,8 @@ static int lite5200_pm_prepare(void) { .type = builtin, .compatible = mpc5200, }, /* efika */ {} }; + u64 regaddr64 = 0; + const u32 *regaddr_p; /* deep sleep? let mpc52xx code handle that */ if (lite5200_pm_target_state == PM_SUSPEND_STANDBY) @@ -60,8 +63,12 @@ static int lite5200_pm_prepare(void) /* map registers */ np = of_find_matching_node(NULL, immr_ids); - mbar = of_iomap(np, 0); + regaddr_p = of_get_address(np, 0, NULL, NULL); + if (regaddr_p) + regaddr64 = of_translate_address(np, regaddr_p); of_node_put(np); + + mbar = ioremap((u32) regaddr64, 0xC000); if (!mbar) { printk(KERN_ERR %s:%i Error mapping registers\n, __func__, __LINE__); return -ENOSYS; @@ -71,6 +78,7 @@ static int lite5200_pm_prepare(void) pic = mbar + 0x500; gps = mbar + 0xb00; gpw = mbar + 0xc00; + pci = mbar + 0xd00; bes = mbar + 0x1200; xlb = mbar + 0x1f00; sram = mbar + 0x8000; @@ -85,6 +93,7 @@ static struct mpc52xx_sdma sbes; static struct mpc52xx_xlb sxlb; static struct mpc52xx_gpio sgps; static struct mpc52xx_gpio_wkup sgpw; +static char spci[0x200]; static void lite5200_save_regs(void) { @@ -94,6 +103,7 @@ static void lite5200_save_regs(void) _memcpy_fromio(sxlb, xlb, sizeof(*xlb)); _memcpy_fromio(sgps, gps, sizeof(*gps)); _memcpy_fromio(sgpw, gpw, sizeof(*gpw)); + _memcpy_fromio(spci, pci, 0x200); _memcpy_fromio(saved_sram, sram, sram_size); } @@ -103,6 +113,8 @@ static void lite5200_restore_regs(void) int i; _memcpy_toio(sram, saved_sram, sram_size); + /* PCI Configuration */ + _memcpy_toio(pci, spci, 0x200); /* * GPIOs. Interrupt Master Enable has higher address then other ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH]: [MPC5200] (v2) Add ATA DMA support
Hi Grant, Thanks for the feedback. New version is attached. Is this a bug fix? If so, please put it into a separate patch. I suppose so, yes. If Ethernet has higher priority than ATA, you can get a deadlock if you try and download a large file over a LAN to disk, for example. But given that nothing other than this patch uses BestComm for ATA do you have any specific reason to split it out into another patch? Good, it can be turned off. Do you think there is any risk to existing ATA users with this patch applied if this is turned off? With the new version, the only risk if this is turned off is the change I've made to bestcomm.h. Other than that, you should get no risk because none of the new code is executed (mwdma_mask and udma_mask are set to 0 if the option is turned off). Can you find any way to avoid this? This could be a performance drain. Previous code had this, so I kept it. Things do seem to work OK without it, so I've removed it... Is there any way to turn on/off DMA at runtime instead of CONFIG time? You could use libata.dma=0 to force DMA off even if it's enabled at CONFIG time. priv-ipb_period = 10 / (ipb_freq / 1000); priv-ata_regs = ata_regs; + priv-ata_regs_pa = (struct mpc52xx_ata __iomem *) res_mem.start; I'm not fond of this. First off, it is *not* __iomem. It is physical address. It would be better to use the offset_of macro to add an offset to the physical base address. Doing it this way forces you to cast and sidestep the compile time checks for incorrect dereferences. I'm afraid I'm not quite sure what you have in mind here, could you please provide a pointer? Thanks, Tim This patch adds MDMA/UDMA support (using BestComm for DMA) on the MPC5200 platform. Based heavily on previous work by Freescale (Bernard Kuhn, John Rigby) and Domen Puncer. Using a SanDisk Extreme IV CF card I get read speeds of approximately 26.70 MB/sec. The BestComm ATA task priority was changed to maximum in bestcomm_priv.h; this fixes a deadlock issue I was experiencing when heavy DMA was occuring on both the ATA and Ethernet BestComm tasks, e.g. when downloading a large file over a LAN to disk. There's also what I believe to be a hardware bug if you have high levels of BestComm ATA DMA activity along with heavy LocalPlus Bus activity; the address bus seems to sometimes get corrupted with ATA commands while the LocalPlus Bus operation is still active (i.e. Chip Select is asserted). I've asked Freescale about this but have not received a reply yet -- if anybody from Freescale has any ideas please contact me; I can supply some analyzer traces if needed. Therefore, for now, do not enable DMA if you need reliable LocalPlus Bus unless you do a fixup in your driver as follows: Locking example: while (test_and_set_bit(0, pata_mpc52xx_ata_dma_lock) != 0) { struct bcom_task_2 *tsk = pata_mpc52xx_ata_dma_task; if(bcom_buffer_done_2(tsk)) return 1; } return 0; (Save the return value to `flags`) Unlocking example: if(flags == 0) clear_bit(0, pata_mpc52xx_ata_dma_lock); Comments and testing would of course be very welcome. Thanks, Signed-off-by: Tim Yamin [EMAIL PROTECTED] diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/ata.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/ata.h 2008-07-02 12:48:14.0 +0100 @@ -16,8 +16,8 @@ struct bcom_ata_bd { u32 status; - u32 dst_pa; u32 src_pa; + u32 dst_pa; }; extern struct bcom_task * diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.c linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.c --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.c 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.c 2008-07-02 12:48:14.0 +0100 @@ -330,11 +330,16 @@ bcom_engine_init(void) /* Init 'always' initiator */ out_8(bcom_eng-regs-ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS); + /* If ATA DMA is enabled, always turn prefetch off (it breaks things) */ +#ifndef CONFIG_PATA_MPC52xx_DMA /* Disable COMM Bus Prefetch on the original 5200; it's broken */ if ((mfspr(SPRN_SVR) MPC5200_SVR_MASK) == MPC5200_SVR) { +#endif regval = in_be16(bcom_eng-regs-PtdCntrl); out_be16(bcom_eng-regs-PtdCntrl, regval | 1); +#ifndef CONFIG_PATA_MPC52xx_DMA } +#endif /* Init lock */ spin_lock_init(bcom_eng-lock); diff -urp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6-ata/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-07-02 12:48:14.0 +0100 @@ -140,15 +140,29
[PATCH]: [MPC5200] (v2) Add ATA DMA support
Changes from previous version: - Add FIFO status error checking code before a DMA transaction starts and after it is completed. - Fix an incorrect check in the previous patch causing spurious dma table too small errors. Tim This patch adds MDMA/UDMA support (using BestComm for DMA) on the MPC5200 platform. Based heavily on previous work by Freescale (Bernard Kuhn, John Rigby) and Domen Puncer. Using a SanDisk Extreme IV CF card I get read speeds of approximately 26.70 MB/sec. The BestComm ATA task priority was changed to maximum in bestcomm_priv.h; this fixes a deadlock issue I was experiencing when heavy DMA was occuring on both the ATA and Ethernet BestComm tasks, e.g. when downloading a large file over a LAN to disk. There's also what I believe to be a hardware bug if you have high levels of BestComm ATA DMA activity along with heavy LocalPlus Bus activity; the address bus seems to sometimes get corrupted with ATA commands while the LocalPlus Bus operation is still active (i.e. Chip Select is asserted). I've asked Freescale about this but have not received a reply yet -- if anybody from Freescale has any ideas please contact me; I can supply some analyzer traces if needed. Therefore, for now, do not enable DMA if you need reliable LocalPlus Bus unless you do a fixup in your driver as follows: Locking example: while (test_and_set_bit(0, pata_mpc52xx_ata_dma_lock) != 0) { struct bcom_task_2 *tsk = pata_mpc52xx_ata_dma_task; if(bcom_buffer_done_2(tsk)) return 1; } return 0; (Save the return value to `flags`) Unlocking example: if(flags == 0) clear_bit(0, pata_mpc52xx_ata_dma_lock); Comments and testing would of course be very welcome. Thanks, Signed-off-by: Tim Yamin [EMAIL PROTECTED] diff -Nurp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/ata.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h 2008-03-18 15:49:53.0 + +++ linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/ata.h 2008-04-15 10:42:38.0 +0100 @@ -16,8 +16,8 @@ struct bcom_ata_bd { u32 status; - u32 dst_pa; u32 src_pa; + u32 dst_pa; }; extern struct bcom_task * diff -Nurp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.c linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.c --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.c 2008-03-18 15:49:53.0 + +++ linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.c 2008-04-15 10:42:38.0 +0100 @@ -330,11 +330,10 @@ /* Init 'always' initiator */ out_8(bcom_eng-regs-ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS); - /* Disable COMM Bus Prefetch on the original 5200; it's broken */ - if ((mfspr(SPRN_SVR) MPC5200_SVR_MASK) == MPC5200_SVR) { - regval = in_be16(bcom_eng-regs-PtdCntrl); - out_be16(bcom_eng-regs-PtdCntrl, regval | 1); - } + /* Disable COMM Bus Prefetch; ATA DMA does not work properly with it + enabled. */ + regval = in_be16(bcom_eng-regs-PtdCntrl); + out_be16(bcom_eng-regs-PtdCntrl, regval | 1); /* Init lock */ spin_lock_init(bcom_eng-lock); diff -Nurp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-03-18 15:49:53.0 + +++ linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-04-15 10:42:38.0 +0100 @@ -17,6 +17,7 @@ #define __BESTCOMM_H__ struct bcom_bd; /* defined later on ... */ +struct bcom_bd_2; /* */ @@ -49,6 +50,22 @@ void* priv; }; +struct bcom_task_2 { + unsigned int tasknum; + unsigned int flags; + int irq; + + struct bcom_bd_2 *bd; + phys_addr_t bd_pa; + void **cookie; + unsigned short index; + unsigned short outdex; + unsigned int num_bd; + unsigned int bd_size; + + void* priv; +}; + #define BCOM_FLAGS_NONE 0xul #define BCOM_FLAGS_ENABLE_TASK (1ul 0) @@ -95,6 +112,11 @@ u32 data[1]; /* variable, but at least 1 */ }; +struct bcom_bd_2 { + u32 status; + u32 data[2]; /* variable, but at least 2 */ +}; + #define BCOM_BD_READY 0x4000ul /** _bcom_next_index - Get next input index. @@ -108,6 +130,12 @@ return ((tsk-index + 1) == tsk-num_bd) ? 0 : tsk-index + 1; } +static inline int +_bcom_next_index_2(struct bcom_task_2 *tsk) +{ + return ((tsk-index + 1) == tsk-num_bd) ? 0 : tsk-index + 1; +} + /** _bcom_next_outdex - Get next output index. * @tsk: pointer to task structure * @@ -129,6 +157,12 @@ return tsk-index == tsk-outdex; } +static inline int +bcom_queue_empty_2(struct bcom_task_2 *tsk) +{ + return tsk-index == tsk-outdex; +} + /** * bcom_queue_full - Checks if a BestComm task BD queue is full * @tsk: The BestComm task structure @@ -151,6 +185,14 @@ return !(tsk-bd[tsk-outdex].status BCOM_BD_READY
[PATCH]: [MPC5200] Add ATA DMA support
This patch adds MDMA/UDMA support (using BestComm for DMA) on the MPC5200 platform. Based heavily on previous work by Freescale (Bernard Kuhn, John Rigby) and Domen Puncer. Using a SanDisk Extreme IV CF card I get read speeds of approximately 26.70 MB/sec. The BestComm ATA task priority was changed to maximum in bestcomm_priv.h; this fixes a deadlock issue I was experiencing when heavy DMA was occuring on both the ATA and Ethernet BestComm tasks, e.g. when downloading a large file over a LAN to disk. There's also what I believe to be a hardware bug if you have high levels of BestComm ATA DMA activity along with heavy LocalPlus Bus activity; the address bus seems to sometimes get corrupted with ATA commands while the LocalPlus Bus operation is still active (i.e. Chip Select is asserted). I've asked Freescale about this but have not received a reply yet -- if anybody from Freescale has any ideas please contact me; I can supply some analyzer traces if needed. Therefore, for now, do not enable DMA if you need reliable LocalPlus Bus unless you do a fixup in your driver as follows: Locking example: while (test_and_set_bit(0, pata_mpc52xx_ata_dma_lock) != 0) { struct bcom_task_2 *tsk = pata_mpc52xx_ata_dma_task; if(bcom_buffer_done_2(tsk)) return 1; } return 0; (Save the return value to `flags`) Unlocking example: if(flags == 0) clear_bit(0, pata_mpc52xx_ata_dma_lock); Comments and testing would of course be very welcome. Thanks, Signed-off-by: Tim Yamin [EMAIL PROTECTED] This patch adds MDMA/UDMA support (using BestComm for DMA) on the MPC5200 platform. Based heavily on previous work by Freescale (Bernard Kuhn, John Rigby) and Domen Puncer. Using a SanDisk Extreme IV CF card I get read speeds of approximately 26.70 MB/sec. The BestComm ATA task priority was changed to maximum in bestcomm_priv.h; this fixes a deadlock issue I was experiencing when heavy DMA was occuring on both the ATA and Ethernet BestComm tasks, e.g. when downloading a large file over a LAN to disk. There's also what I believe to be a hardware bug if you have high levels of BestComm ATA DMA activity along with heavy LocalPlus Bus activity; the address bus seems to sometimes get corrupted with ATA commands while the LocalPlus Bus operation is still active (i.e. Chip Select is asserted). I've asked Freescale about this but have not received a reply yet -- if anybody from Freescale has any ideas please contact me; I can supply some analyzer traces if needed. Therefore, for now, do not enable DMA if you need reliable LocalPlus Bus unless you do a fixup in your driver as follows: Locking example: while (test_and_set_bit(0, pata_mpc52xx_ata_dma_lock) != 0) { struct bcom_task_2 *tsk = pata_mpc52xx_ata_dma_task; if(bcom_buffer_done_2(tsk)) return 1; } return 0; (Save the return value to `flags`) Unlocking example: if(flags == 0) clear_bit(0, pata_mpc52xx_ata_dma_lock); Comments and testing would of course be very welcome. Thanks, Signed-off-by: Tim Yamin [EMAIL PROTECTED] diff -Nurp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/ata.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/ata.h 2008-03-18 15:49:53.0 + +++ linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/ata.h 2008-04-15 10:42:38.0 +0100 @@ -16,8 +16,8 @@ struct bcom_ata_bd { u32 status; - u32 dst_pa; u32 src_pa; + u32 dst_pa; }; extern struct bcom_task * diff -Nurp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.c linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.c --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.c 2008-03-18 15:49:53.0 + +++ linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.c 2008-04-15 10:42:38.0 +0100 @@ -330,11 +330,10 @@ /* Init 'always' initiator */ out_8(bcom_eng-regs-ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS); - /* Disable COMM Bus Prefetch on the original 5200; it's broken */ - if ((mfspr(SPRN_SVR) MPC5200_SVR_MASK) == MPC5200_SVR) { - regval = in_be16(bcom_eng-regs-PtdCntrl); - out_be16(bcom_eng-regs-PtdCntrl, regval | 1); - } + /* Disable COMM Bus Prefetch; ATA DMA does not work properly with it + enabled. */ + regval = in_be16(bcom_eng-regs-PtdCntrl); + out_be16(bcom_eng-regs-PtdCntrl, regval | 1); /* Init lock */ spin_lock_init(bcom_eng-lock); diff -Nurp linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.h --- linux-2.6.26-rc6/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-03-18 15:49:53.0 + +++ linux-2.6.26-rc6.new/arch/powerpc/sysdev/bestcomm/bestcomm.h 2008-04-15 10:42:38.0 +0100 @@ -17,6 +17,7 @@ #define __BESTCOMM_H__ struct bcom_bd; /* defined later
[PATCH]: [MPC5200] Fix lite5200b suspend/resume
Hi, Suspend/resume (echo mem /sys/power/state) does not work for me with vanilla kernels -- the system does not suspend correctly and just hangs. The attached patch fixes this so suspend/resume works: 1) of_iomap does not map the whole 0xC of the MPC5200 for me, so saving registers does not work. Maybe this is just a bug in my DTB? Or is this an of_iomap bug? 2) PCI registers need to be saved and restored. Would it make sense to move struct mpc52xx_pci out of mpc52xx_pci.c and into a header? If somebody else with a lite5200B board could do some testing this would be appreciated as would comments on the above two issues. Thanks, Tim - Current memory remapping is wrong; the remapped area does not have the correct length (0x100 instead of 0xC000) and the system does not power down properly as a result... [of_ioremap bug?] - Make sure the PCI registers are saved and restored, this fixes a kernel panic for me on resume. Signed-off-by: Tim Yamin [EMAIL PROTECTED] --- linux-2.6.26-rc6/arch/powerpc/platforms/52xx/lite5200_pm.c~ 2008-04-17 03:49:44.0 +0100 +++ linux-2.6.26-rc6/arch/powerpc/platforms/52xx/lite5200_pm.c 2008-06-16 15:40:02.0 +0100 @@ -14,6 +14,7 @@ static struct mpc52xx_xlb __iomem *xlb; static struct mpc52xx_gpio __iomem *gps; static struct mpc52xx_gpio_wkup __iomem *gpw; +static void __iomem *pci; static void __iomem *sram; static const int sram_size = 0x4000; /* 16 kBytes */ static void __iomem *mbar; @@ -42,6 +43,9 @@ static int lite5200_pm_prepare(void) { + u64 regaddr64; + const u32 *regaddr_p; + struct device_node *np; const struct of_device_id immr_ids[] = { { .compatible = fsl,mpc5200-immr, }, @@ -60,8 +64,11 @@ /* map registers */ np = of_find_matching_node(NULL, immr_ids); - mbar = of_iomap(np, 0); + regaddr_p = of_get_address(np, 0, NULL, NULL); + regaddr64 = of_translate_address(np, regaddr_p); of_node_put(np); + + mbar = ioremap((u32) regaddr64, 0xC); if (!mbar) { printk(KERN_ERR %s:%i Error mapping registers\n, __func__, __LINE__); return -ENOSYS; @@ -71,6 +78,7 @@ pic = mbar + 0x500; gps = mbar + 0xb00; gpw = mbar + 0xc00; + pci = mbar + 0xd00; bes = mbar + 0x1200; xlb = mbar + 0x1f00; sram = mbar + 0x8000; @@ -85,6 +93,7 @@ static struct mpc52xx_xlb sxlb; static struct mpc52xx_gpio sgps; static struct mpc52xx_gpio_wkup sgpw; +static char spci[0x200]; static void lite5200_save_regs(void) { @@ -94,6 +103,7 @@ _memcpy_fromio(sxlb, xlb, sizeof(*xlb)); _memcpy_fromio(sgps, gps, sizeof(*gps)); _memcpy_fromio(sgpw, gpw, sizeof(*gpw)); + _memcpy_fromio(spci, pci, 0x200); _memcpy_fromio(saved_sram, sram, sram_size); } @@ -103,6 +113,8 @@ int i; _memcpy_toio(sram, saved_sram, sram_size); + /* PCI Configuration */ + _memcpy_toio(pci, spci, 0x200); /* * GPIOs. Interrupt Master Enable has higher address then other ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev