2016-04-21 18:22:11

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

The last approach in the commit 8b3444852a2b ("sata_dwc_460ex: move to generic
DMA driver") to switch to generic DMA engine API wasn't tested on bare metal.
Besides that we expecting new board support coming with the same SATA IP but
with different DMA.

This series is targetting the following things:
- a few bug fixes to the original driver
- a part to fix the DMA engine usage and in particularly dw_dmac driver
- move driver to use generic PHY and "dmas" property which leads to update in DTS

The driver has been tested myself on Sam460ex and WD MyBookLive (apollo3g)
boards. In any case I ask Christian, Måns, and Julian to independently test and
provide Tested-by tag or error report.

Series depends on previously published but not yet fully applied series [1].

[1] http://www.spinics.net/lists/kernel/msg2239735.html

Andy Shevchenko (11):
ata: sata_dwc_460ex: set dma_boundary to 0x1fff
ata: sata_dwc_460ex: burst size must be in items not bytes
ata: sata_dwc_460ex: DMA is always a flow controller
ata: sata_dwc_460ex: select only core part of DMA driver
ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands
ata: sata_dwc_460ex: correct HOSTDEV{P}_FROM_*() macros
ata: sata_dwc_460ex: supply physical address of FIFO to DMA
ata: sata_dwc_460ex: switch to new dmaengine_terminate_* API
ata: sata_dwc_460ex: use devm_ioremap
ata: sata_dwc_460ex: make debug messages neat
powerpc/4xx: Device tree update for the 460ex DWC SATA

Christian Lamparter (1):
ata: sata_dwc_460ex: fix crash on offline links without an attached
drive

Mans Rullgard (11):
ata: sata_dwc_460ex: remove incorrect locking
ata: sata_dwc_460ex: skip dma setup for non-dma commands
ata: sata_dwc_460ex: use "dmas" DT property to find dma channel
ata: sata_dwc_460ex: add phy support
ata: sata_dwc_460ex: get rid of global data
ata: sata_dwc_460ex: remove empty libata callback
ata: sata_dwc_460ex: get rid of some pointless casts
ata: sata_dwc_460ex: get rid of incorrect cast
ata: sata_dwc_460ex: add __iomem to register base pointer
ata: sata_dwc_460ex: use readl/writel_relaxed()
ata: sata_dwc_460ex: tidy up sata_dwc_clear_dmacr()

arch/powerpc/boot/dts/canyonlands.dts | 15 +-
drivers/ata/Kconfig | 12 +-
drivers/ata/sata_dwc_460ex.c | 554 +++++++++++++++++-----------------
3 files changed, 307 insertions(+), 274 deletions(-)

--
2.8.0.rc3


2016-04-21 18:15:52

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 04/23] ata: sata_dwc_460ex: burst size must be in items not bytes

The burst size as defined by DMAengine API is in items of address width. Derive
burst size from AHB_DMA_BRST_DFLT (64 bytes) by dividing it to
DMA_SLAVE_BUSWIDTH_4_BYTES (4 bytes) that gives us 16 items.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index aee8873..4cac27d 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -65,7 +65,7 @@
#define NO_IRQ 0
#endif

-#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length*/
+#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length */

enum {
SATA_DWC_MAX_PORTS = 1,
@@ -318,8 +318,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd
}

sconf.direction = qc->dma_dir;
- sconf.src_maxburst = AHB_DMA_BRST_DFLT;
- sconf.dst_maxburst = AHB_DMA_BRST_DFLT;
+ sconf.src_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */
+ sconf.dst_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */
sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;

--
2.8.0.rc3

2016-04-21 18:15:55

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 03/23] ata: sata_dwc_460ex: set dma_boundary to 0x1fff

The original code states:

Make sure a LLI block is not created that will span 8K max FIS
boundary. If the block spans such a FIS boundary, there is a chance
that a DMA burst will cross that boundary -- this results in an error
in the host controller.

Since we have switched to generic DMAengine API we satisfy above by setting
dma_boundary value to 0x1fff.

Suggested-by: Mans Rullgard <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 7f95389..aee8873 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1151,7 +1151,13 @@ static struct scsi_host_template sata_dwc_sht = {
*/
.sg_tablesize = LIBATA_MAX_PRD,
/* .can_queue = ATA_MAX_QUEUE, */
- .dma_boundary = ATA_DMA_BOUNDARY,
+ /*
+ * Make sure a LLI block is not created that will span 8K max FIS
+ * boundary. If the block spans such a FIS boundary, there is a chance
+ * that a DMA burst will cross that boundary -- this results in an
+ * error in the host controller.
+ */
+ .dma_boundary = 0x1fff /* ATA_DMA_BOUNDARY */,
};

static struct ata_port_operations sata_dwc_ops = {
--
2.8.0.rc3

2016-04-21 18:16:03

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 08/23] ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands

ata_sff_qc_issue() can't handle DMA commands and thus we have to avoid it for
them. Do call ata_bmdma_qc_issue() instead for this case.

Suggested-by: Christian Lamparter <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 038e5fb..845c35d 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1061,10 +1061,12 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
__func__, tag, qc->ap->link.sactive, sactive);

ap->ops->sff_tf_load(ap, &qc->tf);
- sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag,
+ sata_dwc_exec_command_by_tag(ap, &qc->tf, tag,
SATA_DWC_CMD_ISSUED_PEND);
+ } else if (ata_is_dma(qc->tf.protocol)) {
+ return ata_bmdma_qc_issue(qc);
} else {
- ata_sff_qc_issue(qc);
+ return ata_sff_qc_issue(qc);
}
return 0;
}
--
2.8.0.rc3

2016-04-21 18:16:01

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 14/23] ata: sata_dwc_460ex: get rid of some pointless casts

From: Mans Rullgard <[email protected]>

Casting a pointer to unsigned long only to immediately cast it back
to a pointer makes no sense. Fix this.


Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 571ecd1..9e8271d 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -844,26 +844,26 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev)
in_le32(&hsdev->sata_dwc_regs->errmr));
}

-static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base)
+static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base)
{
- port->cmd_addr = (void __iomem *)base + 0x00;
- port->data_addr = (void __iomem *)base + 0x00;
+ port->cmd_addr = base + 0x00;
+ port->data_addr = base + 0x00;

- port->error_addr = (void __iomem *)base + 0x04;
- port->feature_addr = (void __iomem *)base + 0x04;
+ port->error_addr = base + 0x04;
+ port->feature_addr = base + 0x04;

- port->nsect_addr = (void __iomem *)base + 0x08;
+ port->nsect_addr = base + 0x08;

- port->lbal_addr = (void __iomem *)base + 0x0c;
- port->lbam_addr = (void __iomem *)base + 0x10;
- port->lbah_addr = (void __iomem *)base + 0x14;
+ port->lbal_addr = base + 0x0c;
+ port->lbam_addr = base + 0x10;
+ port->lbah_addr = base + 0x14;

- port->device_addr = (void __iomem *)base + 0x18;
- port->command_addr = (void __iomem *)base + 0x1c;
- port->status_addr = (void __iomem *)base + 0x1c;
+ port->device_addr = base + 0x18;
+ port->command_addr = base + 0x1c;
+ port->status_addr = base + 0x1c;

- port->altstatus_addr = (void __iomem *)base + 0x20;
- port->ctl_addr = (void __iomem *)base + 0x20;
+ port->altstatus_addr = base + 0x20;
+ port->ctl_addr = base + 0x20;
}

static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp)
@@ -1253,7 +1253,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
/* Setup port */
host->ports[0]->ioaddr.cmd_addr = base;
host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
- sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base);
+ sata_dwc_setup_port(&host->ports[0]->ioaddr, base);

/* Read the ID and Version Registers */
idr = in_le32(&hsdev->sata_dwc_regs->idr);
--
2.8.0.rc3

2016-04-21 18:16:34

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 10/23] ata: sata_dwc_460ex: add phy support

From: Mans Rullgard <[email protected]>

This adds support for powering on an optional PHY when activating the
device.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/Kconfig | 1 +
drivers/ata/sata_dwc_460ex.c | 22 ++++++++++++++++++++++
2 files changed, 23 insertions(+)

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ede126d..41b0725 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -313,6 +313,7 @@ config ATA_PIIX

config SATA_DWC
tristate "DesignWare Cores SATA support"
+ select GENERIC_PHY
help
This option enables support for the on-chip SATA controller of the
AppliedMicro processor 460EX.
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index daaa8a6..4d23fbd 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -35,6 +35,7 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
#include <linux/libata.h>
#include <linux/slab.h>

@@ -145,6 +146,7 @@ struct sata_dwc_device {
struct ata_host *host;
u8 __iomem *reg_base;
struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */
+ struct phy *phy;
#ifdef CONFIG_SATA_DWC_OLD_DMA
struct dw_dma_chip *dma;
#endif
@@ -948,6 +950,10 @@ static int sata_dwc_port_start(struct ata_port *ap)
if (err)
goto CLEANUP_ALLOC;

+ err = phy_power_on(hsdev->phy);
+ if (err)
+ goto CLEANUP_ALLOC;
+
for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;

@@ -983,11 +989,13 @@ CLEANUP:
static void sata_dwc_port_stop(struct ata_port *ap)
{
struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+ struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);

dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id);

dmaengine_terminate_all(hsdevp->chan);
dma_release_channel(hsdevp->chan);
+ phy_power_off(hsdev->phy);

kfree(hsdevp);
ap->private_data = NULL;
@@ -1323,6 +1331,17 @@ static int sata_dwc_probe(struct platform_device *ofdev)
}
#endif

+ hsdev->phy = devm_phy_optional_get(hsdev->dev, "sata-phy");
+ if (IS_ERR(hsdev->phy)) {
+ err = PTR_ERR(hsdev->phy);
+ hsdev->phy = NULL;
+ goto error_out;
+ }
+
+ err = phy_init(hsdev->phy);
+ if (err)
+ goto error_out;
+
/*
* Now, register with libATA core, this will also initiate the
* device discovery process, invoking our port_start() handler &
@@ -1336,6 +1355,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
return 0;

error_out:
+ phy_exit(hsdev->phy);
iounmap(base);
return err;
}
@@ -1348,6 +1368,8 @@ static int sata_dwc_remove(struct platform_device *ofdev)

ata_host_detach(host);

+ phy_exit(hsdev->phy);
+
#ifdef CONFIG_SATA_DWC_OLD_DMA
/* Free SATA DMA resources */
sata_dwc_dma_exit_old(hsdev);
--
2.8.0.rc3

2016-04-21 18:16:51

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 11/23] ata: sata_dwc_460ex: get rid of global data

From: Mans Rullgard <[email protected]>

This moves all global data into the driver private struct, thus
permitting multiple devices of this type to be used.

The core_scr_read/write() functions are replaced with equivalent
calls to the existing sata_dwc_scr_read/write().

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 79 ++++++++++++++++----------------------------
1 file changed, 29 insertions(+), 50 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 4d23fbd..8e7c1b0 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -146,6 +146,8 @@ struct sata_dwc_device {
struct ata_host *host;
u8 __iomem *reg_base;
struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */
+ u32 sactive_issued;
+ u32 sactive_queued;
struct phy *phy;
#ifdef CONFIG_SATA_DWC_OLD_DMA
struct dw_dma_chip *dma;
@@ -190,14 +192,6 @@ enum {
SATA_DWC_DMA_PENDING_RX = 2,
};

-struct sata_dwc_host_priv {
- void __iomem *scr_addr_sstatus;
- u32 sata_dwc_sactive_issued ;
- u32 sata_dwc_sactive_queued ;
-};
-
-static struct sata_dwc_host_priv host_pvt;
-
/*
* Prototypes
*/
@@ -457,21 +451,11 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val)
return 0;
}

-static u32 core_scr_read(unsigned int scr)
-{
- return in_le32(host_pvt.scr_addr_sstatus + (scr * 4));
-}
-
-static void core_scr_write(unsigned int scr, u32 val)
-{
- out_le32(host_pvt.scr_addr_sstatus + (scr * 4), val);
-}
-
-static void clear_serror(void)
+static void clear_serror(struct ata_port *ap)
{
u32 val;
- val = core_scr_read(SCR_ERROR);
- core_scr_write(SCR_ERROR, val);
+ sata_dwc_scr_read(&ap->link, SCR_ERROR, &val);
+ sata_dwc_scr_write(&ap->link, SCR_ERROR, val);
}

static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
@@ -498,7 +482,7 @@ static void sata_dwc_error_intr(struct ata_port *ap,

ata_ehi_clear_desc(ehi);

- serror = core_scr_read(SCR_ERROR);
+ sata_dwc_scr_read(&ap->link, SCR_ERROR, &serror);
status = ap->ops->sff_check_status(ap);

tag = ap->link.active_tag;
@@ -509,7 +493,7 @@ static void sata_dwc_error_intr(struct ata_port *ap,
hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]);

/* Clear error register and interrupt bit */
- clear_serror();
+ clear_serror(ap);
clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR);

/* This is the only error happening now. TODO check for exact error */
@@ -548,7 +532,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
int handled, num_processed, port = 0;
uint intpr, sactive, sactive2, tag_mask;
struct sata_dwc_device_port *hsdevp;
- host_pvt.sata_dwc_sactive_issued = 0;
+ hsdev->sactive_issued = 0;

spin_lock_irqsave(&host->lock, flags);

@@ -577,7 +561,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND)
dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag);

- host_pvt.sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag);
+ hsdev->sactive_issued |= qcmd_tag_to_mask(tag);

qc = ata_qc_from_tag(ap, tag);
/*
@@ -591,11 +575,11 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
handled = 1;
goto DONE;
}
- sactive = core_scr_read(SCR_ACTIVE);
- tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
+ sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
+ tag_mask = (hsdev->sactive_issued | sactive) ^ sactive;

/* If no sactive issued and tag_mask is zero then this is not NCQ */
- if (host_pvt.sata_dwc_sactive_issued == 0 && tag_mask == 0) {
+ if (hsdev->sactive_issued == 0 && tag_mask == 0) {
if (ap->link.active_tag == ATA_TAG_POISON)
tag = 0;
else
@@ -665,22 +649,19 @@ DRVSTILLBUSY:
*/

/* process completed commands */
- sactive = core_scr_read(SCR_ACTIVE);
- tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
+ sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
+ tag_mask = (hsdev->sactive_issued | sactive) ^ sactive;

- if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \
- tag_mask > 1) {
+ if (sactive != 0 || hsdev->sactive_issued > 1 || tag_mask > 1) {
dev_dbg(ap->dev,
"%s NCQ:sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n",
- __func__, sactive, host_pvt.sata_dwc_sactive_issued,
- tag_mask);
+ __func__, sactive, hsdev->sactive_issued, tag_mask);
}

- if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \
- (host_pvt.sata_dwc_sactive_issued)) {
+ if ((tag_mask | hsdev->sactive_issued) != hsdev->sactive_issued) {
dev_warn(ap->dev,
- "Bad tag mask? sactive=0x%08x (host_pvt.sata_dwc_sactive_issued)=0x%08x tag_mask=0x%08x\n",
- sactive, host_pvt.sata_dwc_sactive_issued, tag_mask);
+ "Bad tag mask? sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n",
+ sactive, hsdev->sactive_issued, tag_mask);
}

/* read just to clear ... not bad if currently still busy */
@@ -742,7 +723,7 @@ STILLBUSY:
* we were processing --we read status as part of processing a completed
* command).
*/
- sactive2 = core_scr_read(SCR_ACTIVE);
+ sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive2);
if (sactive2 != sactive) {
dev_dbg(ap->dev,
"More completed - sactive=0x%x sactive2=0x%x\n",
@@ -828,8 +809,9 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
u8 status = 0;
u32 mask = 0x0;
u8 tag = qc->tag;
+ struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
- host_pvt.sata_dwc_sactive_queued = 0;
+ hsdev->sactive_queued = 0;
dev_dbg(ap->dev, "%s checkstatus? %x\n", __func__, check_status);

if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX)
@@ -842,10 +824,8 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,

/* clear active bit */
mask = (~(qcmd_tag_to_mask(tag)));
- host_pvt.sata_dwc_sactive_queued = (host_pvt.sata_dwc_sactive_queued) \
- & mask;
- host_pvt.sata_dwc_sactive_issued = (host_pvt.sata_dwc_sactive_issued) \
- & mask;
+ hsdev->sactive_queued = hsdev->sactive_queued & mask;
+ hsdev->sactive_issued = hsdev->sactive_issued & mask;
ata_qc_complete(qc);
return 0;
}
@@ -974,7 +954,7 @@ static int sata_dwc_port_start(struct ata_port *ap)
}

/* Clear any error bits before libata starts issuing commands */
- clear_serror();
+ clear_serror(ap);
ap->private_data = hsdevp;
dev_dbg(ap->dev, "%s: done\n", __func__);
return 0;
@@ -1025,7 +1005,7 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap,
* managed SError register for the disk needs to be done before the
* task file is loaded.
*/
- clear_serror();
+ clear_serror(ap);
ata_sff_exec_command(ap, tf);
}

@@ -1078,7 +1058,7 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)
sata_dwc_tf_dump(ap, &qc->tf);

if (start_dma) {
- reg = core_scr_read(SCR_ERROR);
+ sata_dwc_scr_read(&ap->link, SCR_ERROR, &reg);
if (reg & SATA_DWC_SERROR_ERR_BITS) {
dev_err(ap->dev, "%s: ****** SError=0x%08x ******\n",
__func__, reg);
@@ -1140,9 +1120,9 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
}

if (ata_is_ncq(qc->tf.protocol)) {
- sactive = core_scr_read(SCR_ACTIVE);
+ sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
sactive |= (0x00000001 << tag);
- core_scr_write(SCR_ACTIVE, sactive);
+ sata_dwc_scr_write(&ap->link, SCR_ACTIVE, sactive);

dev_dbg(qc->ap->dev,
"%s: tag=%d ap->link.sactive = 0x%08x sactive=0x%08x\n",
@@ -1300,7 +1280,6 @@ static int sata_dwc_probe(struct platform_device *ofdev)
/* Setup port */
host->ports[0]->ioaddr.cmd_addr = base;
host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
- host_pvt.scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base);

/* Read the ID and Version Registers */
--
2.8.0.rc3

2016-04-21 18:16:50

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 22/23] ata: sata_dwc_460ex: make debug messages neat

There is a duplication in the debug messages when accessing SCR registers.
Remove duplication to make the messages neat.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 44dca8c..2d73cdf 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -414,16 +414,16 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
}

*val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4));
- dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
- __func__, link->ap->print_id, scr, *val);
+ dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__,
+ link->ap->print_id, scr, *val);

return 0;
}

static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val)
{
- dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
- __func__, link->ap->print_id, scr, val);
+ dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__,
+ link->ap->print_id, scr, val);
if (scr > SCR_NOTIFICATION) {
dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n",
__func__, scr);
--
2.8.0.rc3

2016-04-21 18:15:59

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 16/23] ata: sata_dwc_460ex: add __iomem to register base pointer

From: Mans Rullgard <[email protected]>

The pointer to the mmio register base is missing the __iomem
annotation. Fix this.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 0eca56f2..42248b2 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -145,7 +145,7 @@ struct sata_dwc_device {
struct ata_probe_ent *pe; /* ptr to probe-ent */
struct ata_host *host;
u8 __iomem *reg_base;
- struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */
+ struct sata_dwc_regs __iomem *sata_dwc_regs; /* DW SATA specific */
u32 sactive_issued;
u32 sactive_queued;
struct phy *phy;
--
2.8.0.rc3

2016-04-21 18:17:26

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 13/23] ata: sata_dwc_460ex: remove empty libata callback

From: Mans Rullgard <[email protected]>

The sata_dwc_qc_prep() does nothing. Use the default ata_noop_qc_prep
instead.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 22 ----------------------
1 file changed, 22 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 5bec790..571ecd1 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1134,27 +1134,6 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
return 0;
}

-/*
- * Function : sata_dwc_qc_prep
- * arguments : ata_queued_cmd *qc
- * Return value : None
- * qc_prep for a particular queued command
- */
-
-static void sata_dwc_qc_prep(struct ata_queued_cmd *qc)
-{
- if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO))
- return;
-
-#ifdef DEBUG_NCQ
- if (qc->tag > 0)
- dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n",
- __func__, qc->tag, qc->ap->link.active_tag);
-
- return ;
-#endif
-}
-
static void sata_dwc_error_handler(struct ata_port *ap)
{
ata_sff_error_handler(ap);
@@ -1214,7 +1193,6 @@ static struct ata_port_operations sata_dwc_ops = {
.error_handler = sata_dwc_error_handler,
.hardreset = sata_dwc_hardreset,

- .qc_prep = sata_dwc_qc_prep,
.qc_issue = sata_dwc_qc_issue,

.scr_read = sata_dwc_scr_read,
--
2.8.0.rc3

2016-04-21 18:17:24

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 20/23] ata: sata_dwc_460ex: tidy up sata_dwc_clear_dmacr()

From: Mans Rullgard <[email protected]>

This consolidates the reads from each of the if/else branches
to one place making the code a lot nicer to look at.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 2029f43..0ef72e4 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -729,15 +729,14 @@ DONE:
static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
{
struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp);
+ u32 dmacr = sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr);

if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) {
- sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
- SATA_DWC_DMACR_RX_CLEAR(
- sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)));
+ dmacr = SATA_DWC_DMACR_RX_CLEAR(dmacr);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr);
} else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) {
- sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
- SATA_DWC_DMACR_TX_CLEAR(
- sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)));
+ dmacr = SATA_DWC_DMACR_TX_CLEAR(dmacr);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr);
} else {
/*
* This should not happen, it indicates the driver is out of
@@ -745,8 +744,7 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
*/
dev_err(hsdev->dev,
"%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n",
- __func__, tag, hsdevp->dma_pending[tag],
- sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
+ __func__, tag, hsdevp->dma_pending[tag], dmacr);
sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
SATA_DWC_DMACR_TXRXCH_CLEAR);
}
--
2.8.0.rc3

2016-04-21 18:17:23

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 17/23] ata: sata_dwc_460ex: supply physical address of FIFO to DMA

DMA operates with physical addresses which is not exactly the same as ioremap()
returns.

Introduce variable to keep physical address of the SATA FIFO register and
supply it when prepare DMA channel.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 42248b2..7810405 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -100,7 +100,7 @@ struct sata_dwc_regs {
u32 versionr; /* Version Register */
u32 idr; /* ID Register */
u32 unimpl[192]; /* Unimplemented */
- u32 dmadr[256]; /* FIFO Locations in DMA Mode */
+ u32 dmadr[256]; /* FIFO Locations in DMA Mode */
};

enum {
@@ -149,6 +149,7 @@ struct sata_dwc_device {
u32 sactive_issued;
u32 sactive_queued;
struct phy *phy;
+ phys_addr_t dmadr;
#ifdef CONFIG_SATA_DWC_OLD_DMA
struct dw_dma_chip *dma;
#endif
@@ -380,15 +381,14 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd
struct ata_port *ap = qc->ap;
struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
- dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr;
struct dma_slave_config sconf;
struct dma_async_tx_descriptor *desc;

if (qc->dma_dir == DMA_DEV_TO_MEM) {
- sconf.src_addr = addr;
+ sconf.src_addr = hsdev->dmadr;
sconf.device_fc = false;
} else { /* DMA_MEM_TO_DEV */
- sconf.dst_addr = addr;
+ sconf.dst_addr = hsdev->dmadr;
sconf.device_fc = false;
}

@@ -411,8 +411,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd
desc->callback = dma_dwc_xfer_done;
desc->callback_param = hsdev;

- dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n",
- __func__, qc->sg, qc->n_elem, &addr);
+ dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pa\n", __func__,
+ qc->sg, qc->n_elem, &hsdev->dmadr);

return desc;
}
@@ -1249,6 +1249,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)

/* Synopsys DWC SATA specific Registers */
hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET;
+ hsdev->dmadr = res->start + SATA_DWC_REG_OFFSET + offsetof(struct sata_dwc_regs, dmadr);

/* Setup port */
host->ports[0]->ioaddr.cmd_addr = base;
--
2.8.0.rc3

2016-04-21 18:18:15

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 21/23] ata: sata_dwc_460ex: use devm_ioremap

This simplifies error handling and cleanup by using devm to manage
IO mappings.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 30 +++++++++++-------------------
1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 0ef72e4..44dca8c 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -139,7 +139,6 @@ struct sata_dwc_device {
struct device *dev; /* generic device struct */
struct ata_probe_ent *pe; /* ptr to probe-ent */
struct ata_host *host;
- u8 __iomem *reg_base;
struct sata_dwc_regs __iomem *sata_dwc_regs; /* DW SATA specific */
u32 sactive_issued;
u32 sactive_queued;
@@ -242,7 +241,7 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
struct sata_dwc_device *hsdev)
{
struct device_node *np = pdev->dev.of_node;
- int err;
+ struct resource *res;

hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL);
if (!hsdev->dma)
@@ -258,21 +257,16 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
}

/* Get physical SATA DMA register base address */
- hsdev->dma->regs = of_iomap(np, 1);
- if (!hsdev->dma->regs) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ hsdev->dma->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hsdev->dma->regs)) {
dev_err(&pdev->dev,
"ioremap failed for AHBDMA register address\n");
- return -ENODEV;
+ return PTR_ERR(hsdev->dma->regs);
}

/* Initialize AHB DMAC */
- err = dw_dma_probe(hsdev->dma);
- if (err) {
- iounmap(hsdev->dma->regs);
- return err;
- }
-
- return 0;
+ return dw_dma_probe(hsdev->dma);
}

static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev)
@@ -281,7 +275,6 @@ static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev)
return;

dw_dma_remove(hsdev->dma);
- iounmap(hsdev->dma->regs);
}

#endif
@@ -1221,6 +1214,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
struct ata_port_info pi = sata_dwc_port_info[0];
const struct ata_port_info *ppi[] = { &pi, NULL };
struct device_node *np = ofdev->dev.of_node;
+ struct resource *res;

/* Allocate DWC SATA device */
host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS);
@@ -1231,13 +1225,13 @@ static int sata_dwc_probe(struct platform_device *ofdev)
host->private_data = hsdev;

/* Ioremap SATA registers */
- base = of_iomap(np, 0);
- if (!base) {
+ res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&ofdev->dev, res);
+ if (IS_ERR(base)) {
dev_err(&ofdev->dev,
"ioremap failed for SATA register address\n");
- return -ENODEV;
+ return PTR_ERR(base);
}
- hsdev->reg_base = base;
dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n");

/* Synopsys DWC SATA specific Registers */
@@ -1302,7 +1296,6 @@ static int sata_dwc_probe(struct platform_device *ofdev)

error_out:
phy_exit(hsdev->phy);
- iounmap(base);
return err;
}

@@ -1321,7 +1314,6 @@ static int sata_dwc_remove(struct platform_device *ofdev)
sata_dwc_dma_exit_old(hsdev);
#endif

- iounmap(hsdev->reg_base);
dev_dbg(&ofdev->dev, "done\n");
return 0;
}
--
2.8.0.rc3

2016-04-21 18:18:36

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 15/23] ata: sata_dwc_460ex: get rid of incorrect cast

From: Mans Rullgard <[email protected]>

The (void *__iomem) cast is wrong. Change the target type of the
"base" pointer to void __iomem instead and drop the cast.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 9e8271d..0eca56f2 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1221,7 +1221,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
struct sata_dwc_device *hsdev;
u32 idr, versionr;
char *ver = (char *)&versionr;
- u8 __iomem *base;
+ void __iomem *base;
int err = 0;
int irq;
struct ata_host *host;
@@ -1248,7 +1248,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n");

/* Synopsys DWC SATA specific Registers */
- hsdev->sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+ hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET;

/* Setup port */
host->ports[0]->ioaddr.cmd_addr = base;
--
2.8.0.rc3

2016-04-21 18:18:39

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 09/23] ata: sata_dwc_460ex: use "dmas" DT property to find dma channel

From: Mans Rullgard <[email protected]>

Currently this driver only works with a DesignWare DMA engine which it
registers manually using the second "reg" address range and interrupt
number from the DT node.

This patch makes the driver instead use the "dmas" property if present,
otherwise optionally falling back on the old way so existing device
trees can continue to work.

With this change, there is no longer any reason to depend on the 460EX
machine type so drop that from Kconfig.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/Kconfig | 11 ++-
drivers/ata/sata_dwc_460ex.c | 198 ++++++++++++++++++++++++++++---------------
2 files changed, 138 insertions(+), 71 deletions(-)

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 7c6e43a..ede126d 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -313,14 +313,21 @@ config ATA_PIIX

config SATA_DWC
tristate "DesignWare Cores SATA support"
- depends on 460EX
- select DW_DMAC_CORE
help
This option enables support for the on-chip SATA controller of the
AppliedMicro processor 460EX.

If unsure, say N.

+config SATA_DWC_OLD_DMA
+ bool "Support old device trees"
+ depends on SATA_DWC
+ select DW_DMAC_CORE
+ default y if 460EX
+ help
+ This option enables support for old device trees without the
+ "dmas" property.
+
config SATA_DWC_DEBUG
bool "Debugging driver version"
depends on SATA_DWC
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 845c35d..daaa8a6 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -30,6 +30,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/dmaengine.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
@@ -42,10 +43,6 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>

-/* Supported DMA engine drivers */
-#include <linux/platform_data/dma-dw.h>
-#include <linux/dma/dw.h>
-
/* These two are defined in "libata.h" */
#undef DRV_NAME
#undef DRV_VERSION
@@ -148,7 +145,9 @@ struct sata_dwc_device {
struct ata_host *host;
u8 __iomem *reg_base;
struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */
+#ifdef CONFIG_SATA_DWC_OLD_DMA
struct dw_dma_chip *dma;
+#endif
};

#define SATA_DWC_QCMD_MAX 32
@@ -159,7 +158,6 @@ struct sata_dwc_device_port {
int dma_pending[SATA_DWC_QCMD_MAX];

/* DMA info */
- struct dw_dma_slave *dws;
struct dma_chan *chan;
struct dma_async_tx_descriptor *desc[SATA_DWC_QCMD_MAX];
u32 dma_interrupt_count;
@@ -198,13 +196,6 @@ struct sata_dwc_host_priv {

static struct sata_dwc_host_priv host_pvt;

-static struct dw_dma_slave sata_dwc_dma_dws = {
- .src_id = 0,
- .dst_id = 0,
- .m_master = 1,
- .p_master = 0,
-};
-
/*
* Prototypes
*/
@@ -215,6 +206,99 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status);
static void sata_dwc_port_stop(struct ata_port *ap);
static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag);

+#ifdef CONFIG_SATA_DWC_OLD_DMA
+
+#include <linux/platform_data/dma-dw.h>
+#include <linux/dma/dw.h>
+
+static struct dw_dma_slave sata_dwc_dma_dws = {
+ .src_id = 0,
+ .dst_id = 0,
+ .m_master = 1,
+ .p_master = 0,
+};
+
+static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct dw_dma_slave *dws = &sata_dwc_dma_dws;
+
+ if (dws->dma_dev != chan->device->dev)
+ return false;
+
+ chan->private = dws;
+ return true;
+}
+
+static int sata_dwc_dma_get_channel_old(struct sata_dwc_device_port *hsdevp)
+{
+ struct sata_dwc_device *hsdev = hsdevp->hsdev;
+ struct dw_dma_slave *dws = &sata_dwc_dma_dws;
+ dma_cap_mask_t mask;
+
+ dws->dma_dev = hsdev->dev;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ /* Acquire DMA channel */
+ hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
+ if (!hsdevp->chan) {
+ dev_err(hsdev->dev, "%s: dma channel unavailable\n",
+ __func__);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static int sata_dwc_dma_init_old(struct platform_device *pdev,
+ struct sata_dwc_device *hsdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int err;
+
+ hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL);
+ if (!hsdev->dma)
+ return -ENOMEM;
+
+ hsdev->dma->dev = &pdev->dev;
+
+ /* Get SATA DMA interrupt number */
+ hsdev->dma->irq = irq_of_parse_and_map(np, 1);
+ if (hsdev->dma->irq == NO_IRQ) {
+ dev_err(&pdev->dev, "no SATA DMA irq\n");
+ return -ENODEV;
+ }
+
+ /* Get physical SATA DMA register base address */
+ hsdev->dma->regs = of_iomap(np, 1);
+ if (!hsdev->dma->regs) {
+ dev_err(&pdev->dev,
+ "ioremap failed for AHBDMA register address\n");
+ return -ENODEV;
+ }
+
+ /* Initialize AHB DMAC */
+ err = dw_dma_probe(hsdev->dma);
+ if (err) {
+ iounmap(hsdev->dma->regs);
+ return err;
+ }
+
+ return 0;
+}
+
+static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev)
+{
+ if (!hsdev->dma)
+ return;
+
+ dw_dma_remove(hsdev->dma);
+ iounmap(hsdev->dma->regs);
+}
+
+#endif
+
static const char *get_prot_descript(u8 protocol)
{
switch ((enum ata_tf_protocols)protocol) {
@@ -783,18 +867,6 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev)
in_le32(&hsdev->sata_dwc_regs->errmr));
}

-static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param)
-{
- struct sata_dwc_device_port *hsdevp = param;
- struct dw_dma_slave *dws = hsdevp->dws;
-
- if (dws->dma_dev != chan->device->dev)
- return false;
-
- chan->private = dws;
- return true;
-}
-
static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base)
{
port->cmd_addr = (void __iomem *)base + 0x00;
@@ -817,6 +889,26 @@ static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base)
port->ctl_addr = (void __iomem *)base + 0x20;
}

+static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp)
+{
+ struct sata_dwc_device *hsdev = hsdevp->hsdev;
+ struct device *dev = hsdev->dev;
+
+#ifdef CONFIG_SATA_DWC_OLD_DMA
+ if (!of_find_property(dev->of_node, "dmas", NULL))
+ return sata_dwc_dma_get_channel_old(hsdevp);
+#endif
+
+ hsdevp->chan = dma_request_chan(dev, "sata-dma");
+ if (IS_ERR(hsdevp->chan)) {
+ dev_err(dev, "failed to allocate dma channel: %ld\n",
+ PTR_ERR(hsdevp->chan));
+ return PTR_ERR(hsdevp->chan);
+ }
+
+ return 0;
+}
+
/*
* Function : sata_dwc_port_start
* arguments : struct ata_ioports *port
@@ -829,7 +921,6 @@ static int sata_dwc_port_start(struct ata_port *ap)
struct sata_dwc_device *hsdev;
struct sata_dwc_device_port *hsdevp = NULL;
struct device *pdev;
- dma_cap_mask_t mask;
int i;

hsdev = HSDEV_FROM_AP(ap);
@@ -853,20 +944,9 @@ static int sata_dwc_port_start(struct ata_port *ap)
}
hsdevp->hsdev = hsdev;

- hsdevp->dws = &sata_dwc_dma_dws;
- hsdevp->dws->dma_dev = hsdev->dev;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- /* Acquire DMA channel */
- hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
- if (!hsdevp->chan) {
- dev_err(hsdev->dev, "%s: dma channel unavailable\n",
- __func__);
- err = -EAGAIN;
+ err = sata_dwc_dma_get_channel(hsdevp);
+ if (err)
goto CLEANUP_ALLOC;
- }

for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
@@ -1221,33 +1301,9 @@ static int sata_dwc_probe(struct platform_device *ofdev)
dev_notice(&ofdev->dev, "id %d, controller version %c.%c%c\n",
idr, ver[0], ver[1], ver[2]);

- /* Get SATA DMA interrupt number */
- hsdev->dma->irq = irq_of_parse_and_map(np, 1);
- if (hsdev->dma->irq == NO_IRQ) {
- dev_err(&ofdev->dev, "no SATA DMA irq\n");
- err = -ENODEV;
- goto error_iomap;
- }
-
- /* Get physical SATA DMA register base address */
- hsdev->dma->regs = of_iomap(np, 1);
- if (!hsdev->dma->regs) {
- dev_err(&ofdev->dev,
- "ioremap failed for AHBDMA register address\n");
- err = -ENODEV;
- goto error_iomap;
- }
-
/* Save dev for later use in dev_xxx() routines */
hsdev->dev = &ofdev->dev;

- hsdev->dma->dev = &ofdev->dev;
-
- /* Initialize AHB DMAC */
- err = dw_dma_probe(hsdev->dma);
- if (err)
- goto error_dma_iomap;
-
/* Enable SATA Interrupts */
sata_dwc_enable_interrupts(hsdev);

@@ -1259,6 +1315,14 @@ static int sata_dwc_probe(struct platform_device *ofdev)
goto error_out;
}

+#ifdef CONFIG_SATA_DWC_OLD_DMA
+ if (!of_find_property(np, "dmas", NULL)) {
+ err = sata_dwc_dma_init_old(ofdev, hsdev);
+ if (err)
+ goto error_out;
+ }
+#endif
+
/*
* Now, register with libATA core, this will also initiate the
* device discovery process, invoking our port_start() handler &
@@ -1272,11 +1336,6 @@ static int sata_dwc_probe(struct platform_device *ofdev)
return 0;

error_out:
- /* Free SATA DMA resources */
- dw_dma_remove(hsdev->dma);
-error_dma_iomap:
- iounmap(hsdev->dma->regs);
-error_iomap:
iounmap(base);
return err;
}
@@ -1289,10 +1348,11 @@ static int sata_dwc_remove(struct platform_device *ofdev)

ata_host_detach(host);

+#ifdef CONFIG_SATA_DWC_OLD_DMA
/* Free SATA DMA resources */
- dw_dma_remove(hsdev->dma);
+ sata_dwc_dma_exit_old(hsdev);
+#endif

- iounmap(hsdev->dma->regs);
iounmap(hsdev->reg_base);
dev_dbg(&ofdev->dev, "done\n");
return 0;
--
2.8.0.rc3

2016-04-21 18:18:35

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 18/23] ata: sata_dwc_460ex: switch to new dmaengine_terminate_* API

Convert dmaengine_terminate_all() calls to synchronous and asynchronous
versions where appropriate.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 7810405..229e122 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -968,7 +968,7 @@ static void sata_dwc_port_stop(struct ata_port *ap)

dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id);

- dmaengine_terminate_all(hsdevp->chan);
+ dmaengine_terminate_sync(hsdevp->chan);
dma_release_channel(hsdevp->chan);
phy_power_off(hsdev->phy);

--
2.8.0.rc3

2016-04-21 18:19:46

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 19/23] ata: sata_dwc_460ex: use readl/writel_relaxed()

From: Mans Rullgard <[email protected]>

Rename the register access macros and use standard _relaxed()
ops instead of __raw variants with explicit byte swapping.

The original driver used the ppc-specific in/out_le32(). When it
was adapted to other systems, these were added to the driver
under ifdefs. However, those names are not defined as macros on
ppc, so it ended up replacing them there as well with altered
semantics. This patch restores the original semantics on ppc and
makes the accesses no less strict on other systems.

Also fixes too many sparse warnings to count.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 91 +++++++++++++++++++++-----------------------
1 file changed, 43 insertions(+), 48 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 229e122..2029f43 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -51,13 +51,8 @@
#define DRV_NAME "sata-dwc"
#define DRV_VERSION "1.3"

-#ifndef out_le32
-#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (void __iomem *)(a))
-#endif
-
-#ifndef in_le32
-#define in_le32(a) __le32_to_cpu(__raw_readl((void __iomem *)(a)))
-#endif
+#define sata_dwc_writel(a, v) writel_relaxed(v, a)
+#define sata_dwc_readl(a) readl_relaxed(a)

#ifndef NO_IRQ
#define NO_IRQ 0
@@ -425,7 +420,7 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
return -EINVAL;
}

- *val = in_le32(link->ap->ioaddr.scr_addr + (scr * 4));
+ *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4));
dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
__func__, link->ap->print_id, scr, *val);

@@ -441,7 +436,7 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val)
__func__, scr);
return -EINVAL;
}
- out_le32(link->ap->ioaddr.scr_addr + (scr * 4), val);
+ sata_dwc_writel(link->ap->ioaddr.scr_addr + (scr * 4), val);

return 0;
}
@@ -455,8 +450,8 @@ static void clear_serror(struct ata_port *ap)

static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
{
- out_le32(&hsdev->sata_dwc_regs->intpr,
- in_le32(&hsdev->sata_dwc_regs->intpr));
+ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr,
+ sata_dwc_readl(&hsdev->sata_dwc_regs->intpr));
}

static u32 qcmd_tag_to_mask(u8 tag)
@@ -532,7 +527,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
spin_lock_irqsave(&host->lock, flags);

/* Read the interrupt register */
- intpr = in_le32(&hsdev->sata_dwc_regs->intpr);
+ intpr = sata_dwc_readl(&hsdev->sata_dwc_regs->intpr);

ap = host->ports[port];
hsdevp = HSDEVP_FROM_AP(ap);
@@ -551,7 +546,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
if (intpr & SATA_DWC_INTPR_NEWFP) {
clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP);

- tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr));
+ tag = (u8)(sata_dwc_readl(&hsdev->sata_dwc_regs->fptagr));
dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag);
if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND)
dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag);
@@ -736,13 +731,13 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp);

if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) {
- out_le32(&(hsdev->sata_dwc_regs->dmacr),
- SATA_DWC_DMACR_RX_CLEAR(
- in_le32(&(hsdev->sata_dwc_regs->dmacr))));
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+ SATA_DWC_DMACR_RX_CLEAR(
+ sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)));
} else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) {
- out_le32(&(hsdev->sata_dwc_regs->dmacr),
- SATA_DWC_DMACR_TX_CLEAR(
- in_le32(&(hsdev->sata_dwc_regs->dmacr))));
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+ SATA_DWC_DMACR_TX_CLEAR(
+ sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)));
} else {
/*
* This should not happen, it indicates the driver is out of
@@ -751,9 +746,9 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
dev_err(hsdev->dev,
"%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n",
__func__, tag, hsdevp->dma_pending[tag],
- in_le32(&hsdev->sata_dwc_regs->dmacr));
- out_le32(&(hsdev->sata_dwc_regs->dmacr),
- SATA_DWC_DMACR_TXRXCH_CLEAR);
+ sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+ SATA_DWC_DMACR_TXRXCH_CLEAR);
}
}

@@ -778,7 +773,7 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
__func__, qc->tag, qc->tf.command,
get_dma_dir_descript(qc->dma_dir),
get_prot_descript(qc->tf.protocol),
- in_le32(&(hsdev->sata_dwc_regs->dmacr)));
+ sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
}
#endif

@@ -787,7 +782,7 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
dev_err(ap->dev,
"%s DMA protocol RX and TX DMA not pending dmacr: 0x%08x\n",
__func__,
- in_le32(&(hsdev->sata_dwc_regs->dmacr)));
+ sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
}

hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_NONE;
@@ -828,20 +823,20 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev)
{
/* Enable selective interrupts by setting the interrupt maskregister*/
- out_le32(&hsdev->sata_dwc_regs->intmr,
- SATA_DWC_INTMR_ERRM |
- SATA_DWC_INTMR_NEWFPM |
- SATA_DWC_INTMR_PMABRTM |
- SATA_DWC_INTMR_DMATM);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->intmr,
+ SATA_DWC_INTMR_ERRM |
+ SATA_DWC_INTMR_NEWFPM |
+ SATA_DWC_INTMR_PMABRTM |
+ SATA_DWC_INTMR_DMATM);
/*
* Unmask the error bits that should trigger an error interrupt by
* setting the error mask register.
*/
- out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);

dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n",
- __func__, in_le32(&hsdev->sata_dwc_regs->intmr),
- in_le32(&hsdev->sata_dwc_regs->errmr));
+ __func__, sata_dwc_readl(&hsdev->sata_dwc_regs->intmr),
+ sata_dwc_readl(&hsdev->sata_dwc_regs->errmr));
}

static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base)
@@ -938,14 +933,14 @@ static int sata_dwc_port_start(struct ata_port *ap)
if (ap->port_no == 0) {
dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n",
__func__);
- out_le32(&hsdev->sata_dwc_regs->dmacr,
- SATA_DWC_DMACR_TXRXCH_CLEAR);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+ SATA_DWC_DMACR_TXRXCH_CLEAR);

dev_dbg(ap->dev, "%s: setting burst size in DBTSR\n",
__func__);
- out_le32(&hsdev->sata_dwc_regs->dbtsr,
- (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
- SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr,
+ (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+ SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
}

/* Clear any error bits before libata starts issuing commands */
@@ -1060,11 +1055,11 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)
}

if (dir == DMA_TO_DEVICE)
- out_le32(&hsdev->sata_dwc_regs->dmacr,
- SATA_DWC_DMACR_TXCHEN);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+ SATA_DWC_DMACR_TXCHEN);
else
- out_le32(&hsdev->sata_dwc_regs->dmacr,
- SATA_DWC_DMACR_RXCHEN);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+ SATA_DWC_DMACR_RXCHEN);

/* Enable AHB DMA transfer on the specified channel */
dmaengine_submit(desc);
@@ -1150,13 +1145,13 @@ static int sata_dwc_hardreset(struct ata_link *link, unsigned int *class,
sata_dwc_enable_interrupts(hsdev);

/* Reconfigure the DMA control register */
- out_le32(&hsdev->sata_dwc_regs->dmacr,
- SATA_DWC_DMACR_TXRXCH_CLEAR);
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+ SATA_DWC_DMACR_TXRXCH_CLEAR);

/* Reconfigure the DMA Burst Transaction Size register */
- out_le32(&hsdev->sata_dwc_regs->dbtsr,
- SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
- SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT));
+ sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr,
+ SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+ SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT));

return ret;
}
@@ -1257,8 +1252,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
sata_dwc_setup_port(&host->ports[0]->ioaddr, base);

/* Read the ID and Version Registers */
- idr = in_le32(&hsdev->sata_dwc_regs->idr);
- versionr = in_le32(&hsdev->sata_dwc_regs->versionr);
+ idr = sata_dwc_readl(&hsdev->sata_dwc_regs->idr);
+ versionr = sata_dwc_readl(&hsdev->sata_dwc_regs->versionr);
dev_notice(&ofdev->dev, "id %d, controller version %c.%c%c\n",
idr, ver[0], ver[1], ver[2]);

--
2.8.0.rc3

2016-04-21 18:20:10

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 07/23] ata: sata_dwc_460ex: skip dma setup for non-dma commands

From: Mans Rullgard <[email protected]>

Calling dmaengine_prep_slave_sg() for non-dma ATA commands is
unnecessary at best and could be harmful if the dma driver reacts
badly to this. It also causes this driver to print a bogus error
message in these cases.

This patch changes sata_dwc_qc_issue() to only do the dma setup
for dma commands and also reports an error to libata if if fails.

Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 35 +++++++++--------------------------
1 file changed, 9 insertions(+), 26 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 1250e18..038e5fb 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1023,36 +1023,12 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc)
sata_dwc_bmdma_start_by_tag(qc, tag);
}

-/*
- * Function : sata_dwc_qc_prep_by_tag
- * arguments : ata_queued_cmd *qc, u8 tag
- * Return value : None
- * qc_prep for a particular queued command based on tag
- */
-static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)
-{
- struct dma_async_tx_descriptor *desc;
- struct ata_port *ap = qc->ap;
- struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
-
- dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n",
- __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir),
- qc->n_elem);
-
- desc = dma_dwc_xfer_setup(qc);
- if (!desc) {
- dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n",
- __func__);
- return;
- }
- hsdevp->desc[tag] = desc;
-}
-
static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
{
u32 sactive;
u8 tag = qc->tag;
struct ata_port *ap = qc->ap;
+ struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);

#ifdef DEBUG_NCQ
if (qc->tag > 0 || ap->link.sactive > 1)
@@ -1066,7 +1042,14 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)

if (!ata_is_ncq(qc->tf.protocol))
tag = 0;
- sata_dwc_qc_prep_by_tag(qc, tag);
+
+ if (ata_is_dma(qc->tf.protocol)) {
+ hsdevp->desc[tag] = dma_dwc_xfer_setup(qc);
+ if (!hsdevp->desc[tag])
+ return AC_ERR_SYSTEM;
+ } else {
+ hsdevp->desc[tag] = NULL;
+ }

if (ata_is_ncq(qc->tf.protocol)) {
sactive = core_scr_read(SCR_ACTIVE);
--
2.8.0.rc3

2016-04-21 18:20:09

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 23/23] powerpc/4xx: Device tree update for the 460ex DWC SATA

Device tree update for the Applied micro processor 460ex on-chip SATA to use
"dmas" property.

Signed-off-by: Andy Shevchenko <[email protected]>
---
arch/powerpc/boot/dts/canyonlands.dts | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index 3dc75de..549c24c 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -190,12 +190,21 @@
/* DMA */ 0x2 &UIC0 0xc 0x4>;
};

+ AHBDMA: dma@bffd0800 {
+ compatible = "snps,dma-spear1340";
+ reg = <4 0xbffd0800 0x400>;
+ interrupt-parent = <&UIC3>;
+ interrupts = <0x5 0x4>;
+ #dma-cells = <3>;
+ };
+
SATA0: sata@bffd1000 {
compatible = "amcc,sata-460ex";
- reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
+ reg = <4 0xbffd1000 0x800>;
interrupt-parent = <&UIC3>;
- interrupts = <0x0 0x4 /* SATA */
- 0x5 0x4>; /* AHBDMA */
+ interrupts = <0x0 0x4>;
+ dmas = <&AHBDMA 0 1 0>;
+ dma-names = "sata-dma";
};

POB0: opb {
--
2.8.0.rc3

2016-04-21 18:20:06

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 12/23] ata: sata_dwc_460ex: correct HOSTDEV{P}_FROM_*() macros

Here we refactor HOSTDEV{P}_FROM_*() macros to fit one line and fix the
definition of HSDEV_FROM_HSDEVP() where wrong name of the parameter waas used.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 8e7c1b0..5bec790 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -168,18 +168,13 @@ struct sata_dwc_device_port {
};

/*
- * Commonly used DWC SATA driver Macros
+ * Commonly used DWC SATA driver macros
*/
-#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)\
- (host)->private_data)
-#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)\
- (ap)->host->private_data)
-#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)\
- (ap)->private_data)
-#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)\
- (qc)->ap->host->private_data)
-#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)\
- (hsdevp)->hsdev)
+#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)(host)->private_data)
+#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)(ap)->host->private_data)
+#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)(ap)->private_data)
+#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)(qc)->ap->host->private_data)
+#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)(p)->hsdev)

enum {
SATA_DWC_CMD_ISSUED_NOT = 0,
--
2.8.0.rc3

2016-04-21 18:20:04

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 06/23] ata: sata_dwc_460ex: select only core part of DMA driver

There is no need to have a platform driver compiled since the DMA driver is
used as a library.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index cfa936a..7c6e43a 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -314,7 +314,7 @@ config ATA_PIIX
config SATA_DWC
tristate "DesignWare Cores SATA support"
depends on 460EX
- select DW_DMAC
+ select DW_DMAC_CORE
help
This option enables support for the on-chip SATA controller of the
AppliedMicro processor 460EX.
--
2.8.0.rc3

2016-04-21 18:22:09

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 01/23] ata: sata_dwc_460ex: remove incorrect locking

From: Mans Rullgard <[email protected]>

This lock is already taken in ata_scsi_queuecmd() a few levels up the
call stack so attempting to take it here is an error. Moreover, it is
pointless in the first place since it only protects a single, atomic
assignment.

Enabling lock debugging gives the following output:

=============================================
[ INFO: possible recursive locking detected ]
4.4.0-rc5+ #189 Not tainted
---------------------------------------------
kworker/u2:3/37 is trying to acquire lock:
(&(&host->lock)->rlock){-.-...}, at: [<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c

but task is already holding lock:
(&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330

other info that might help us debug this:
Possible unsafe locking scenario:

CPU0
----
lock(&(&host->lock)->rlock);
lock(&(&host->lock)->rlock);

*** DEADLOCK ***
May be due to missing lock nesting notation

4 locks held by kworker/u2:3/37:
#0: ("events_unbound"){.+.+.+}, at: [<9003a0a4>] process_one_work+0x12c/0x430
#1: ((&entry->work)){+.+.+.}, at: [<9003a0a4>] process_one_work+0x12c/0x430
#2: (&bdev->bd_mutex){+.+.+.}, at: [<9011fd54>] __blkdev_get+0x50/0x380
#3: (&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330

stack backtrace:
CPU: 0 PID: 37 Comm: kworker/u2:3 Not tainted 4.4.0-rc5+ #189
Workqueue: events_unbound async_run_entry_fn
Stack : 90b38e30 00000021 00000003 9b2a6040 00000000 9005f3f0 904fc8dc 00000025
906b96e4 00000000 90528648 9b3336c4 904fc8dc 9009bf18 00000002 00000004
00000000 00000000 9b3336c4 9b3336e4 904fc8dc 9003d074 00000000 90500000
9005e738 00000000 00000000 00000000 00000000 00000000 00000000 00000000
6e657665 755f7374 756f626e 0000646e 00000000 00000000 9b00ca00 9b025000
...
Call Trace:
[<90009d6c>] show_stack+0x88/0xa4
[<90057744>] __lock_acquire+0x1ce8/0x2154
[<900583e4>] lock_acquire+0x64/0x8c
[<9045ff10>] _raw_spin_lock_irqsave+0x54/0x78
[<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c
[<90283484>] sata_dwc_qc_issue+0x1a8/0x24c
[<9026b39c>] ata_qc_issue+0x1f0/0x410
[<90273c6c>] ata_scsi_translate+0xb4/0x200
[<90276234>] ata_scsi_queuecmd+0xb4/0x330
[<9025800c>] scsi_dispatch_cmd+0xd0/0x128
[<90259934>] scsi_request_fn+0x58c/0x638
[<901a3e50>] __blk_run_queue+0x40/0x5c
[<901a83d4>] blk_queue_bio+0x27c/0x28c
[<901a5914>] generic_make_request+0xf0/0x188
[<901a5a54>] submit_bio+0xa8/0x194
[<9011adcc>] submit_bh_wbc.isra.23+0x15c/0x17c
[<9011c908>] block_read_full_page+0x3e4/0x428
[<9009e2e0>] do_read_cache_page+0xac/0x210
[<9009fd90>] read_cache_page+0x18/0x24
[<901bbd18>] read_dev_sector+0x38/0xb0
[<901bd174>] msdos_partition+0xb4/0x5c0
[<901bcb8c>] check_partition+0x140/0x274
[<901bba60>] rescan_partitions+0xa0/0x2b0
[<9011ff68>] __blkdev_get+0x264/0x380
[<901201ac>] blkdev_get+0x128/0x36c
[<901b9378>] add_disk+0x3c0/0x4bc
[<90268268>] sd_probe_async+0x100/0x224
[<90043a44>] async_run_entry_fn+0x50/0x124
[<9003a11c>] process_one_work+0x1a4/0x430
[<9003a4f4>] worker_thread+0x14c/0x4fc
[<900408f4>] kthread+0xd0/0xe8
[<90004338>] ret_from_kernel_thread+0x14/0x1c

Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex")
Signed-off-by: Mans Rullgard <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 2cb6f7e..5213e22 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -924,15 +924,13 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap,
struct ata_taskfile *tf,
u8 tag, u32 cmd_issued)
{
- unsigned long flags;
struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);

dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command,
ata_get_cmd_descript(tf->command), tag);

- spin_lock_irqsave(&ap->host->lock, flags);
hsdevp->cmd_issued[tag] = cmd_issued;
- spin_unlock_irqrestore(&ap->host->lock, flags);
+
/*
* Clear SError before executing a new command.
* sata_dwc_scr_write and read can not be used here. Clearing the PM
--
2.8.0.rc3

2016-04-21 18:22:07

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 05/23] ata: sata_dwc_460ex: DMA is always a flow controller

In the original code the DMA is always a flow controller. Set this accordingly
in updated code.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 4cac27d..1250e18 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -311,7 +311,7 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd

if (qc->dma_dir == DMA_DEV_TO_MEM) {
sconf.src_addr = addr;
- sconf.device_fc = true;
+ sconf.device_fc = false;
} else { /* DMA_MEM_TO_DEV */
sconf.dst_addr = addr;
sconf.device_fc = false;
--
2.8.0.rc3

2016-04-21 18:23:00

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 02/23] ata: sata_dwc_460ex: fix crash on offline links without an attached drive

From: Christian Lamparter <[email protected]>

This patch fixes Machine Check "Data Write PLB Error" which happens
when libata-sff's ata_sff_dev_select is trying to write into the
device_addr in order to select a drive. However, SATA has no master
or slave devices like the old ATA Bus, therefore selecting a
different drive is kind of pointless.

Data Write PLB Error
Oops: Machine check, sig: 7 [#1]
PowerPC 44x Platform
Modules linked in:
CPU: 0 PID: 508 Comm: scsi_eh_0 Not tainted 4.6.0-rc3-next-20160412+ #10
[...]
NIP [c027e820] ata_sff_dev_select+0x3c/0x44
LR [c027e810] ata_sff_dev_select+0x2c/0x44
Call Trace:
[cec31cd0] [c027da00] ata_sff_postreset+0x40/0xb4 (unreliable)
[cec31ce0] [c027a03c] ata_eh_reset+0x5cc/0x928
[cec31d60] [c027a840] ata_eh_recover+0x330/0x10bc
[cec31df0] [c027bae0] ata_do_eh+0x4c/0xa4
[...]

Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/ata/sata_dwc_460ex.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 5213e22..7f95389 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1134,6 +1134,11 @@ static int sata_dwc_hardreset(struct ata_link *link, unsigned int *class,
return ret;
}

+static void sata_dwc_dev_select(struct ata_port *ap, unsigned int device)
+{
+ /* SATA DWC is master only */
+}
+
/*
* scsi mid-layer and libata interface structures
*/
@@ -1164,6 +1169,8 @@ static struct ata_port_operations sata_dwc_ops = {
.port_start = sata_dwc_port_start,
.port_stop = sata_dwc_port_stop,

+ .sff_dev_select = sata_dwc_dev_select,
+
.bmdma_setup = sata_dwc_bmdma_setup,
.bmdma_start = sata_dwc_bmdma_start,
};
--
2.8.0.rc3

2016-04-21 19:59:38

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v1 23/23] powerpc/4xx: Device tree update for the 460ex DWC SATA

On Thu, Apr 21, 2016 at 1:15 PM, Andy Shevchenko
<[email protected]> wrote:
> Device tree update for the Applied micro processor 460ex on-chip SATA to use
> "dmas" property.
> Signed-off-by: Andy Shevchenko <[email protected]>
> ---
> arch/powerpc/boot/dts/canyonlands.dts | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)

I see you have maintained compatibility in the driver for old DTs, so:

Acked-by: Rob Herring <[email protected]>

2016-04-21 20:25:34

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex: move to generic
> DMA driver") to switch to generic DMA engine API wasn't tested on bare metal.
> Besides that we expecting new board support coming with the same SATA IP but
> with different DMA.
>
> This series is targetting the following things:
> - a few bug fixes to the original driver
> - a part to fix the DMA engine usage and in particularly dw_dmac driver
> - move driver to use generic PHY and "dmas" property which leads to update in DTS
>
> The driver has been tested myself on Sam460ex and WD MyBookLive (apollo3g)
> boards. In any case I ask Christian, M?ns, and Julian to independently test and
> provide Tested-by tag or error report.
I did a test run on my WD MyBook Live. I applied all the patches in
this series on top of the topic/dw branch of Vinod Koul:
<https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>

Tested-by: Christian Lamparter <[email protected]>
---
results for my old ST3808110AS HDD. filesystem is ext4.

# hdparm -t /dev/sda

/dev/sda:
Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec

# bonnie++ -u mbl
Using uid:1000, gid:1000.
Writing a byte at a time...done
Writing intelligently...done
Rewriting...done
Reading a byte at a time...done
Reading intelligently...done
start 'em...done...done...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version 1.97 ------Sequential Output------ --Sequential Input- --Random-
Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
mbl 496M 98 99 26011 21 17589 20 538 99 80138 39 208.9 8
Latency 95267us 1409ms 295ms 26947us 9644us 1787ms
Version 1.97 ------Sequential Create------ --------Random Create--------
mbl -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 6959 78 +++++ +++ 5197 40 7250 79 +++++ +++ 4718 37
Latency 149ms 6742us 212ms 177ms 767us 217ms
1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms


2016-04-22 11:02:30

by Julian Margetson

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On 4/21/2016 4:25 PM, Christian Lamparter wrote:
> On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
>> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex: move to generic
>> DMA driver") to switch to generic DMA engine API wasn't tested on bare metal.
>> Besides that we expecting new board support coming with the same SATA IP but
>> with different DMA.
>>
>> This series is targetting the following things:
>> - a few bug fixes to the original driver
>> - a part to fix the DMA engine usage and in particularly dw_dmac driver
>> - move driver to use generic PHY and "dmas" property which leads to update in DTS
>>
>> The driver has been tested myself on Sam460ex and WD MyBookLive (apollo3g)
>> boards. In any case I ask Christian, M?ns, and Julian to independently test and
>> provide Tested-by tag or error report.
> I did a test run on my WD MyBook Live. I applied all the patches in
> this series on top of the topic/dw branch of Vinod Koul:
> <https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>
>
> Tested-by: Christian Lamparter <[email protected]>
> ---
> results for my old ST3808110AS HDD. filesystem is ext4.
>
> # hdparm -t /dev/sda
>
> /dev/sda:
> Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec
>
> # bonnie++ -u mbl
> Using uid:1000, gid:1000.
> Writing a byte at a time...done
> Writing intelligently...done
> Rewriting...done
> Reading a byte at a time...done
> Reading intelligently...done
> start 'em...done...done...done...done...done...
> Create files in sequential order...done.
> Stat files in sequential order...done.
> Delete files in sequential order...done.
> Create files in random order...done.
> Stat files in random order...done.
> Delete files in random order...done.
> Version 1.97 ------Sequential Output------ --Sequential Input- --Random-
> Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
> Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
> mbl 496M 98 99 26011 21 17589 20 538 99 80138 39 208.9 8
> Latency 95267us 1409ms 295ms 26947us 9644us 1787ms
> Version 1.97 ------Sequential Create------ --------Random Create--------
> mbl -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
> files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
> 16 6959 78 +++++ +++ 5197 40 7250 79 +++++ +++ 4718 37
> Latency 149ms 6742us 212ms 177ms 767us 217ms
> 1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms
>
>
>
>
Again on copy partitions .


Attachments:
sam460ex_7.log (55.72 kB)

2016-04-22 11:19:35

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On Friday, April 22, 2016 06:50:44 AM Julian Margetson wrote:
> On 4/21/2016 4:25 PM, Christian Lamparter wrote:
> > On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
> >> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex: move to generic
> >> DMA driver") to switch to generic DMA engine API wasn't tested on bare metal.
> >> Besides that we expecting new board support coming with the same SATA IP but
> >> with different DMA.
> >>
> >> The driver has been tested myself on Sam460ex and WD MyBookLive (apollo3g)
> >> boards. In any case I ask Christian, M?ns, and Julian to independently test and
> >> provide Tested-by tag or error report.
> > I did a test run on my WD MyBook Live. I applied all the patches in
> > this series on top of the topic/dw branch of Vinod Koul:
> > <https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>
> >
> > Tested-by: Christian Lamparter <[email protected]>
> > ---
> > results for my old ST3808110AS HDD. filesystem is ext4.
> >
> > # hdparm -t /dev/sda
> >
> > /dev/sda:
> > Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec
> >
> > # bonnie++ -u mbl
> > Using uid:1000, gid:1000.
> > Writing a byte at a time...done
> > Writing intelligently...done
> > Rewriting...done
> > Reading a byte at a time...done
> > Reading intelligently...done
> > start 'em...done...done...done...done...done...
> > Create files in sequential order...done.
> > Stat files in sequential order...done.
> > Delete files in sequential order...done.
> > Create files in random order...done.
> > Stat files in random order...done.
> > Delete files in random order...done.
> > Version 1.97 ------Sequential Output------ --Sequential Input- --Random-
> > Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
> > Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
> > mbl 496M 98 99 26011 21 17589 20 538 99 80138 39 208.9 8
> > Latency 95267us 1409ms 295ms 26947us 9644us 1787ms
> > Version 1.97 ------Sequential Create------ --------Random Create--------
> > mbl -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
> > files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
> > 16 6959 78 +++++ +++ 5197 40 7250 79 +++++ +++ 4718 37
> > Latency 149ms 6742us 212ms 177ms 767us 217ms
> > 1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms
> >
> Again on copy partitions .

Ok, here's the copy from my mail off-list.

Well, a unrelated driver "m41t80" caused a crash:
[ 12.912739] Oops: Kernel access of bad area, sig: 11 [#3]
[ 12.912743] PREEMPT Canyonlands
[ 12.912753] CPU: 0 PID: 1413 Comm: irq/45-m41t80 Tainted: G D 4.6.0-rc4-next-20160421-sam460ex-jm #1
[ 12.912757] task: ea9834e0 ti: eea6c000 task.ti: eea6c000
[ 12.912760] NIP: c0224480 LR: c0023494 CTR: c0042508
[ 12.912764] REGS: eea6daf0 TRAP: 0300 Tainted: G D (4.6.0-rc4-next-20160421-sam460ex-jm)
[ 12.912774] MSR: 00029000 <CE,EE,ME> CR: 24008282 XER: 00000000
[ 12.912825] DEAR: 00000008 ESR: 00000000
[...]
[ 12.912927] --- interrupt: 300 at mutex_lock+0x0/0x1c
[ 12.912927] LR = m41t80_handle_irq+0x28/0xac
[ 12.912932] [eea6de40] [00000000] (null) (unreliable)
[ 12.912938] [eea6de60] [c004ffac] irq_thread_fn+0x2c/0x48
[ 12.912944] [eea6de80] [c00501cc] irq_thread+0xc4/0x160
[ 12.912951] [eea6ded0] [c003a3f8] kthread+0xc8/0xcc
[ 12.912957] [eea6df40] [c000aee8] ret_from_kernel_thread+0x5c/0x64
[ 12.912960] Instruction dump:
[ 12.912974] 80010014 7fc3f378 bbc10008 7c0803a6 38210010 4be24ca8 9421ffd0 7c0802a6
[ 12.912987] bf210014 90010034 3b4302d8 812302ec <83890008> 812302d8 7f9a4840 419e011c
[ 12.912995] Fixing recursive fault but reboot is needed!
^^^ "reboot is needed!"

Another thing that came to my mind: Have you checked if your hard drive
and the cables are ok? Are there any pending sectors or suspicious smart
values? Has the drive passed the extended offline test?

Otherwise, I can't reproduce the error with my MyBook system. I've tested
your kernel and it worked on the device without crashing. (I copied/dd'ed
80GB from and back to the hard-drive. It was long and boring, but I didn't
encounter any issues and the crc32 matched).

Sorry, but I can't help you if I can't reproduce it... And short of sending
your box to test, I see no efficient way to debug it. However, what I can
do, if you are interested: I have a few "build your own" My Book Live kits.
It just needs a 3.5" hard-drive and 12v power adapter. If you are interested
PM me off-list, this way you can verify that the kernels you build do work,
just in case this error is due to a hardware issue (zapped controller,
bad ram/drive/cable?) with your sam460ex box.

Regards,
Christian

2016-04-22 11:33:26

by David Laight

[permalink] [raw]
Subject: RE: [PATCH v1 08/23] ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands

From: Andy Shevchenko
> Sent: 21 April 2016 19:15
> ata_sff_qc_issue() can't handle DMA commands and thus we have to avoid it for
> them. Do call ata_bmdma_qc_issue() instead for this case.
>
> Suggested-by: Christian Lamparter <[email protected]>
> Signed-off-by: Andy Shevchenko <[email protected]>
> ---
> drivers/ata/sata_dwc_460ex.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
> index 038e5fb..845c35d 100644
> --- a/drivers/ata/sata_dwc_460ex.c
> +++ b/drivers/ata/sata_dwc_460ex.c
> @@ -1061,10 +1061,12 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
> __func__, tag, qc->ap->link.sactive, sactive);
>
> ap->ops->sff_tf_load(ap, &qc->tf);
> - sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag,
> + sata_dwc_exec_command_by_tag(ap, &qc->tf, tag,
> SATA_DWC_CMD_ISSUED_PEND);
> + } else if (ata_is_dma(qc->tf.protocol)) {
> + return ata_bmdma_qc_issue(qc);
> } else {
> - ata_sff_qc_issue(qc);
> + return ata_sff_qc_issue(qc);
> }
> return 0;
> }

I'd nuke those 'else if', they make it very hard to read.
I Think the code is:

sata_dwc_exec_command_by_tag(...);
return 0;
}

if (ata_is_dma(qc->tf.protocol))
return ata_bmdma_qc_issue(qc);

return ata_sff_qc_issue(qc);
}

David


2016-04-22 11:44:20

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH v1 08/23] ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands

On Friday, April 22, 2016 11:32:00 AM David Laight wrote:
> From: Andy Shevchenko
> > Sent: 21 April 2016 19:15
> > ata_sff_qc_issue() can't handle DMA commands and thus we have to avoid it for
> > them. Do call ata_bmdma_qc_issue() instead for this case.
> >
> > Suggested-by: Christian Lamparter <[email protected]>
> > Signed-off-by: Andy Shevchenko <[email protected]>
> > ---
> > drivers/ata/sata_dwc_460ex.c | 6 ++++--
> > 1 file changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
> > index 038e5fb..845c35d 100644
> > --- a/drivers/ata/sata_dwc_460ex.c
> > +++ b/drivers/ata/sata_dwc_460ex.c
> > @@ -1061,10 +1061,12 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
> > __func__, tag, qc->ap->link.sactive, sactive);
> >
> > ap->ops->sff_tf_load(ap, &qc->tf);
> > - sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag,
> > + sata_dwc_exec_command_by_tag(ap, &qc->tf, tag,
> > SATA_DWC_CMD_ISSUED_PEND);
> > + } else if (ata_is_dma(qc->tf.protocol)) {
> > + return ata_bmdma_qc_issue(qc);
> > } else {
> > - ata_sff_qc_issue(qc);
> > + return ata_sff_qc_issue(qc);
> > }
> > return 0;
> > }
>
> I'd nuke those 'else if', they make it very hard to read.
> I Think the code is:
>
> sata_dwc_exec_command_by_tag(...);
> return 0;
> }
>
> if (ata_is_dma(qc->tf.protocol))
> return ata_bmdma_qc_issue(qc);
>
> return ata_sff_qc_issue(qc);
> }

What about something like this instead? ata_bmdma_qc_issue already calls
ata_sff_qc_issue, if it's not a dma transfere anyway [0].
---
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 6a61184..67cce54 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1096,12 +1096,9 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
ap->ops->sff_tf_load(ap, &qc->tf);
sata_dwc_exec_command_by_tag(ap, &qc->tf, tag,
SATA_DWC_CMD_ISSUED_PEND);
- } else if (ata_is_dma(qc->tf.protocol)) {
+ return 0;
+ } else
return ata_bmdma_qc_issue(qc);
- } else {
- return ata_sff_qc_issue(qc);
- }
- return 0;
}

static void sata_dwc_error_handler(struct ata_port *ap)
---

[0] <http://lxr.free-electrons.com/source/drivers/ata/libata-sff.c#L2787>

2016-04-22 13:13:13

by Sergei Shtylyov

[permalink] [raw]
Subject: Re: [PATCH v1 03/23] ata: sata_dwc_460ex: set dma_boundary to 0x1fff

Hello.

On 04/21/2016 09:15 PM, Andy Shevchenko wrote:

> The original code states:
>
> Make sure a LLI block is not created that will span 8K max FIS
> boundary. If the block spans such a FIS boundary, there is a chance
> that a DMA burst will cross that boundary -- this results in an error
> in the host controller.
>
> Since we have switched to generic DMAengine API we satisfy above by setting
> dma_boundary value to 0x1fff.
>
> Suggested-by: Mans Rullgard <[email protected]>
> Signed-off-by: Andy Shevchenko <[email protected]>
> ---
> drivers/ata/sata_dwc_460ex.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
> index 7f95389..aee8873 100644
> --- a/drivers/ata/sata_dwc_460ex.c
> +++ b/drivers/ata/sata_dwc_460ex.c
> @@ -1151,7 +1151,13 @@ static struct scsi_host_template sata_dwc_sht = {
> */
> .sg_tablesize = LIBATA_MAX_PRD,
> /* .can_queue = ATA_MAX_QUEUE, */
> - .dma_boundary = ATA_DMA_BOUNDARY,
> + /*
> + * Make sure a LLI block is not created that will span 8K max FIS
> + * boundary. If the block spans such a FIS boundary, there is a chance
> + * that a DMA burst will cross that boundary -- this results in an
> + * error in the host controller.
> + */
> + .dma_boundary = 0x1fff /* ATA_DMA_BOUNDARY */,

Not ~0x1fff?

[...]

MBR, Sergei

2016-04-23 12:02:56

by Julian Margetson

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On 4/22/2016 7:06 AM, Christian Lamparter wrote:
> On Friday, April 22, 2016 06:50:44 AM Julian Margetson wrote:
>> On 4/21/2016 4:25 PM, Christian Lamparter wrote:
>>> On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
>>>> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex: move to generic
>>>> DMA driver") to switch to generic DMA engine API wasn't tested on bare metal.
>>>> Besides that we expecting new board support coming with the same SATA IP but
>>>> with different DMA.
>>>>
>>>> The driver has been tested myself on Sam460ex and WD MyBookLive (apollo3g)
>>>> boards. In any case I ask Christian, M?ns, and Julian to independently test and
>>>> provide Tested-by tag or error report.
>>> I did a test run on my WD MyBook Live. I applied all the patches in
>>> this series on top of the topic/dw branch of Vinod Koul:
>>> <https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>
>>>
>>> Tested-by: Christian Lamparter<[email protected]>
>>> ---
>>> results for my old ST3808110AS HDD. filesystem is ext4.
>>>
>>> # hdparm -t /dev/sda
>>>
>>> /dev/sda:
>>> Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec
>>>
>>> # bonnie++ -u mbl
>>> Using uid:1000, gid:1000.
>>> Writing a byte at a time...done
>>> Writing intelligently...done
>>> Rewriting...done
>>> Reading a byte at a time...done
>>> Reading intelligently...done
>>> start 'em...done...done...done...done...done...
>>> Create files in sequential order...done.
>>> Stat files in sequential order...done.
>>> Delete files in sequential order...done.
>>> Create files in random order...done.
>>> Stat files in random order...done.
>>> Delete files in random order...done.
>>> Version 1.97 ------Sequential Output------ --Sequential Input- --Random-
>>> Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
>>> Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
>>> mbl 496M 98 99 26011 21 17589 20 538 99 80138 39 208.9 8
>>> Latency 95267us 1409ms 295ms 26947us 9644us 1787ms
>>> Version 1.97 ------Sequential Create------ --------Random Create--------
>>> mbl -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
>>> files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
>>> 16 6959 78 +++++ +++ 5197 40 7250 79 +++++ +++ 4718 37
>>> Latency 149ms 6742us 212ms 177ms 767us 217ms
>>> 1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms
>>>
>> Again on copy partitions .
> Ok, here's the copy from my mail off-list.
>
> Well, a unrelated driver "m41t80" caused a crash:
> [ 12.912739] Oops: Kernel access of bad area, sig: 11 [#3]
> [ 12.912743] PREEMPT Canyonlands
> [ 12.912753] CPU: 0 PID: 1413 Comm: irq/45-m41t80 Tainted: G D 4.6.0-rc4-next-20160421-sam460ex-jm #1
> [ 12.912757] task: ea9834e0 ti: eea6c000 task.ti: eea6c000
> [ 12.912760] NIP: c0224480 LR: c0023494 CTR: c0042508
> [ 12.912764] REGS: eea6daf0 TRAP: 0300 Tainted: G D (4.6.0-rc4-next-20160421-sam460ex-jm)
> [ 12.912774] MSR: 00029000 <CE,EE,ME> CR: 24008282 XER: 00000000
> [ 12.912825] DEAR: 00000008 ESR: 00000000
> [...]
> [ 12.912927] --- interrupt: 300 at mutex_lock+0x0/0x1c
> [ 12.912927] LR = m41t80_handle_irq+0x28/0xac
> [ 12.912932] [eea6de40] [00000000] (null) (unreliable)
> [ 12.912938] [eea6de60] [c004ffac] irq_thread_fn+0x2c/0x48
> [ 12.912944] [eea6de80] [c00501cc] irq_thread+0xc4/0x160
> [ 12.912951] [eea6ded0] [c003a3f8] kthread+0xc8/0xcc
> [ 12.912957] [eea6df40] [c000aee8] ret_from_kernel_thread+0x5c/0x64
> [ 12.912960] Instruction dump:
> [ 12.912974] 80010014 7fc3f378 bbc10008 7c0803a6 38210010 4be24ca8 9421ffd0 7c0802a6
> [ 12.912987] bf210014 90010034 3b4302d8 812302ec <83890008> 812302d8 7f9a4840 419e011c
> [ 12.912995] Fixing recursive fault but reboot is needed!
> ^^^ "reboot is needed!"
>
> Another thing that came to my mind: Have you checked if your hard drive
> and the cables are ok? Are there any pending sectors or suspicious smart
> values? Has the drive passed the extended offline test?
>
> Otherwise, I can't reproduce the error with my MyBook system. I've tested
> your kernel and it worked on the device without crashing. (I copied/dd'ed
> 80GB from and back to the hard-drive. It was long and boring, but I didn't
> encounter any issues and the crc32 matched).
>
> Sorry, but I can't help you if I can't reproduce it... And short of sending
> your box to test, I see no efficient way to debug it. However, what I can
> do, if you are interested: I have a few "build your own" My Book Live kits.
> It just needs a 3.5" hard-drive and 12v power adapter. If you are interested
> PM me off-list, this way you can verify that the kernels you build do work,
> just in case this error is due to a hardware issue (zapped controller,
> bad ram/drive/cable?) with your sam460ex box.
>
> Regards,
> Christian
>
>
My Hardware seems ok.
I have swapped cables and drives between the SII3512 pci controller and
the DWC controller.
No issues when connected to the SII3512 pci controller .
The DWC controller works ok under AmigaOS 4.1FE so that does not appear
to be a problem.

Regards
Julian







2016-04-23 15:44:59

by Julian Margetson

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On 4/23/2016 8:02 AM, Julian Margetson wrote:
> On 4/22/2016 7:06 AM, Christian Lamparter wrote:
>> On Friday, April 22, 2016 06:50:44 AM Julian Margetson wrote:
>>> On 4/21/2016 4:25 PM, Christian Lamparter wrote:
>>>> On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
>>>>> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex:
>>>>> move to generic
>>>>> DMA driver") to switch to generic DMA engine API wasn't tested on
>>>>> bare metal.
>>>>> Besides that we expecting new board support coming with the same
>>>>> SATA IP but
>>>>> with different DMA.
>>>>>
>>>>> The driver has been tested myself on Sam460ex and WD MyBookLive
>>>>> (apollo3g)
>>>>> boards. In any case I ask Christian, Måns, and Julian to
>>>>> independently test and
>>>>> provide Tested-by tag or error report.
>>>> I did a test run on my WD MyBook Live. I applied all the patches in
>>>> this series on top of the topic/dw branch of Vinod Koul:
>>>> <https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>
>>>>
>>>> Tested-by: Christian Lamparter<[email protected]>
>>>> ---
>>>> results for my old ST3808110AS HDD. filesystem is ext4.
>>>>
>>>> # hdparm -t /dev/sda
>>>>
>>>> /dev/sda:
>>>> Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec
>>>>
>>>> # bonnie++ -u mbl
>>>> Using uid:1000, gid:1000.
>>>> Writing a byte at a time...done
>>>> Writing intelligently...done
>>>> Rewriting...done
>>>> Reading a byte at a time...done
>>>> Reading intelligently...done
>>>> start 'em...done...done...done...done...done...
>>>> Create files in sequential order...done.
>>>> Stat files in sequential order...done.
>>>> Delete files in sequential order...done.
>>>> Create files in random order...done.
>>>> Stat files in random order...done.
>>>> Delete files in random order...done.
>>>> Version 1.97 ------Sequential Output------ --Sequential
>>>> Input- --Random-
>>>> Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr-
>>>> --Block-- --Seeks--
>>>> Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec
>>>> %CP /sec %CP
>>>> mbl 496M 98 99 26011 21 17589 20 538 99 80138
>>>> 39 208.9 8
>>>> Latency 95267us 1409ms 295ms 26947us 9644us
>>>> 1787ms
>>>> Version 1.97 ------Sequential Create------ --------Random
>>>> Create--------
>>>> mbl -Create-- --Read--- -Delete-- -Create--
>>>> --Read--- -Delete--
>>>> files /sec %CP /sec %CP /sec %CP /sec %CP /sec
>>>> %CP /sec %CP
>>>> 16 6959 78 +++++ +++ 5197 40 7250 79 +++++
>>>> +++ 4718 37
>>>> Latency 149ms 6742us 212ms 177ms 767us
>>>> 217ms
>>>> 1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms
>>>>
>>>>
>>> Again on copy partitions .
>> Ok, here's the copy from my mail off-list.
>>
>> Well, a unrelated driver "m41t80" caused a crash:
>> [ 12.912739] Oops: Kernel access of bad area, sig: 11 [#3]
>> [ 12.912743] PREEMPT Canyonlands
>> [ 12.912753] CPU: 0 PID: 1413 Comm: irq/45-m41t80 Tainted: G
>> D 4.6.0-rc4-next-20160421-sam460ex-jm #1
>> [ 12.912757] task: ea9834e0 ti: eea6c000 task.ti: eea6c000
>> [ 12.912760] NIP: c0224480 LR: c0023494 CTR: c0042508
>> [ 12.912764] REGS: eea6daf0 TRAP: 0300 Tainted: G D
>> (4.6.0-rc4-next-20160421-sam460ex-jm)
>> [ 12.912774] MSR: 00029000 <CE,EE,ME> CR: 24008282 XER: 00000000
>> [ 12.912825] DEAR: 00000008 ESR: 00000000
>> [...]
>> [ 12.912927] --- interrupt: 300 at mutex_lock+0x0/0x1c
>> [ 12.912927] LR = m41t80_handle_irq+0x28/0xac
>> [ 12.912932] [eea6de40] [00000000] (null) (unreliable)
>> [ 12.912938] [eea6de60] [c004ffac] irq_thread_fn+0x2c/0x48
>> [ 12.912944] [eea6de80] [c00501cc] irq_thread+0xc4/0x160
>> [ 12.912951] [eea6ded0] [c003a3f8] kthread+0xc8/0xcc
>> [ 12.912957] [eea6df40] [c000aee8] ret_from_kernel_thread+0x5c/0x64
>> [ 12.912960] Instruction dump:
>> [ 12.912974] 80010014 7fc3f378 bbc10008 7c0803a6 38210010 4be24ca8
>> 9421ffd0 7c0802a6
>> [ 12.912987] bf210014 90010034 3b4302d8 812302ec <83890008>
>> 812302d8 7f9a4840 419e011c
>> [ 12.912995] Fixing recursive fault but reboot is needed!
>> ^^^ "reboot is needed!"
>>
>> Another thing that came to my mind: Have you checked if your hard drive
>> and the cables are ok? Are there any pending sectors or suspicious smart
>> values? Has the drive passed the extended offline test?
>> Otherwise, I can't reproduce the error with my MyBook system. I've
>> tested
>> your kernel and it worked on the device without crashing. (I
>> copied/dd'ed
>> 80GB from and back to the hard-drive. It was long and boring, but I
>> didn't
>> encounter any issues and the crc32 matched).
>>
>> Sorry, but I can't help you if I can't reproduce it... And short of
>> sending
>> your box to test, I see no efficient way to debug it. However, what I
>> can
>> do, if you are interested: I have a few "build your own" My Book Live
>> kits.
>> It just needs a 3.5" hard-drive and 12v power adapter. If you are
>> interested
>> PM me off-list, this way you can verify that the kernels you build do
>> work,
>> just in case this error is due to a hardware issue (zapped controller,
>> bad ram/drive/cable?) with your sam460ex box.
>>
>> Regards,
>> Christian
>>
>>
> My Hardware seems ok.
> I have swapped cables and drives between the SII3512 pci controller
> and the DWC controller.
> No issues when connected to the SII3512 pci controller .
> The DWC controller works ok under AmigaOS 4.1FE so that does not
> appear to be a problem.
>
> Regards
> Julian
>
>
>
>
>
>
Test with kernel compiled with no other sata controllers included.
Freshly formatted harddrive with one ntfs partition. MS-DOs partition
table.
Booted from USB thumb drive.
Keyboard and mouse freeze as soon as gparted is run.


Attachments:
sam460ex_dmesg_8.log (67.29 kB)
Sam460ex_8.log (48.91 kB)
Download all attachments

2016-04-23 15:45:28

by Julian Margetson

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On 4/23/2016 8:02 AM, Julian Margetson wrote:
> On 4/22/2016 7:06 AM, Christian Lamparter wrote:
>> On Friday, April 22, 2016 06:50:44 AM Julian Margetson wrote:
>>> On 4/21/2016 4:25 PM, Christian Lamparter wrote:
>>>> On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
>>>>> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex:
>>>>> move to generic
>>>>> DMA driver") to switch to generic DMA engine API wasn't tested on
>>>>> bare metal.
>>>>> Besides that we expecting new board support coming with the same
>>>>> SATA IP but
>>>>> with different DMA.
>>>>>
>>>>> The driver has been tested myself on Sam460ex and WD MyBookLive
>>>>> (apollo3g)
>>>>> boards. In any case I ask Christian, Måns, and Julian to
>>>>> independently test and
>>>>> provide Tested-by tag or error report.
>>>> I did a test run on my WD MyBook Live. I applied all the patches in
>>>> this series on top of the topic/dw branch of Vinod Koul:
>>>> <https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>
>>>>
>>>> Tested-by: Christian Lamparter<[email protected]>
>>>> ---
>>>> results for my old ST3808110AS HDD. filesystem is ext4.
>>>>
>>>> # hdparm -t /dev/sda
>>>>
>>>> /dev/sda:
>>>> Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec
>>>>
>>>> # bonnie++ -u mbl
>>>> Using uid:1000, gid:1000.
>>>> Writing a byte at a time...done
>>>> Writing intelligently...done
>>>> Rewriting...done
>>>> Reading a byte at a time...done
>>>> Reading intelligently...done
>>>> start 'em...done...done...done...done...done...
>>>> Create files in sequential order...done.
>>>> Stat files in sequential order...done.
>>>> Delete files in sequential order...done.
>>>> Create files in random order...done.
>>>> Stat files in random order...done.
>>>> Delete files in random order...done.
>>>> Version 1.97 ------Sequential Output------ --Sequential
>>>> Input- --Random-
>>>> Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr-
>>>> --Block-- --Seeks--
>>>> Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec
>>>> %CP /sec %CP
>>>> mbl 496M 98 99 26011 21 17589 20 538 99 80138
>>>> 39 208.9 8
>>>> Latency 95267us 1409ms 295ms 26947us 9644us
>>>> 1787ms
>>>> Version 1.97 ------Sequential Create------ --------Random
>>>> Create--------
>>>> mbl -Create-- --Read--- -Delete-- -Create--
>>>> --Read--- -Delete--
>>>> files /sec %CP /sec %CP /sec %CP /sec %CP /sec
>>>> %CP /sec %CP
>>>> 16 6959 78 +++++ +++ 5197 40 7250 79 +++++
>>>> +++ 4718 37
>>>> Latency 149ms 6742us 212ms 177ms 767us
>>>> 217ms
>>>> 1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms
>>>>
>>>>
>>> Again on copy partitions .
>> Ok, here's the copy from my mail off-list.
>>
>> Well, a unrelated driver "m41t80" caused a crash:
>> [ 12.912739] Oops: Kernel access of bad area, sig: 11 [#3]
>> [ 12.912743] PREEMPT Canyonlands
>> [ 12.912753] CPU: 0 PID: 1413 Comm: irq/45-m41t80 Tainted: G
>> D 4.6.0-rc4-next-20160421-sam460ex-jm #1
>> [ 12.912757] task: ea9834e0 ti: eea6c000 task.ti: eea6c000
>> [ 12.912760] NIP: c0224480 LR: c0023494 CTR: c0042508
>> [ 12.912764] REGS: eea6daf0 TRAP: 0300 Tainted: G D
>> (4.6.0-rc4-next-20160421-sam460ex-jm)
>> [ 12.912774] MSR: 00029000 <CE,EE,ME> CR: 24008282 XER: 00000000
>> [ 12.912825] DEAR: 00000008 ESR: 00000000
>> [...]
>> [ 12.912927] --- interrupt: 300 at mutex_lock+0x0/0x1c
>> [ 12.912927] LR = m41t80_handle_irq+0x28/0xac
>> [ 12.912932] [eea6de40] [00000000] (null) (unreliable)
>> [ 12.912938] [eea6de60] [c004ffac] irq_thread_fn+0x2c/0x48
>> [ 12.912944] [eea6de80] [c00501cc] irq_thread+0xc4/0x160
>> [ 12.912951] [eea6ded0] [c003a3f8] kthread+0xc8/0xcc
>> [ 12.912957] [eea6df40] [c000aee8] ret_from_kernel_thread+0x5c/0x64
>> [ 12.912960] Instruction dump:
>> [ 12.912974] 80010014 7fc3f378 bbc10008 7c0803a6 38210010 4be24ca8
>> 9421ffd0 7c0802a6
>> [ 12.912987] bf210014 90010034 3b4302d8 812302ec <83890008>
>> 812302d8 7f9a4840 419e011c
>> [ 12.912995] Fixing recursive fault but reboot is needed!
>> ^^^ "reboot is needed!"
>>
>> Another thing that came to my mind: Have you checked if your hard drive
>> and the cables are ok? Are there any pending sectors or suspicious smart
>> values? Has the drive passed the extended offline test?
>> Otherwise, I can't reproduce the error with my MyBook system. I've
>> tested
>> your kernel and it worked on the device without crashing. (I
>> copied/dd'ed
>> 80GB from and back to the hard-drive. It was long and boring, but I
>> didn't
>> encounter any issues and the crc32 matched).
>>
>> Sorry, but I can't help you if I can't reproduce it... And short of
>> sending
>> your box to test, I see no efficient way to debug it. However, what I
>> can
>> do, if you are interested: I have a few "build your own" My Book Live
>> kits.
>> It just needs a 3.5" hard-drive and 12v power adapter. If you are
>> interested
>> PM me off-list, this way you can verify that the kernels you build do
>> work,
>> just in case this error is due to a hardware issue (zapped controller,
>> bad ram/drive/cable?) with your sam460ex box.
>>
>> Regards,
>> Christian
>>
>>
> My Hardware seems ok.
> I have swapped cables and drives between the SII3512 pci controller
> and the DWC controller.
> No issues when connected to the SII3512 pci controller .
> The DWC controller works ok under AmigaOS 4.1FE so that does not
> appear to be a problem.
>
> Regards
> Julian
>
>
>
>
>
>
Test with kernel compiled with no other sata controllers included.
Freshly formatted harddrive with one ntfs partition. MS-DOS partition
table.
Booted from USB thumb drive.
Keyboard and mouse freeze as soon as gparted is run.


Attachments:
sam460ex_dmesg_8.log (67.29 kB)
Sam460ex_8.log (48.91 kB)
Download all attachments

2016-04-23 19:41:33

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On Saturday, April 23, 2016 11:44:09 AM Julian Margetson wrote:
> On 4/23/2016 8:02 AM, Julian Margetson wrote:
> > On 4/22/2016 7:06 AM, Christian Lamparter wrote:
> >> On Friday, April 22, 2016 06:50:44 AM Julian Margetson wrote:
> >>> On 4/21/2016 4:25 PM, Christian Lamparter wrote:
> >>>> On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
> >>>>> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex:
> >>>>> move to generic
> >>>>> DMA driver") to switch to generic DMA engine API wasn't tested on
> >>>>> bare metal.
> >>>>> Besides that we expecting new board support coming with the same
> >>>>> SATA IP but
> >>>>> with different DMA.
> >>>>>
> >>>>> The driver has been tested myself on Sam460ex and WD MyBookLive
> >>>>> (apollo3g)
> >>>>> boards. In any case I ask Christian, M?ns, and Julian to
> >>>>> independently test and
> >>>>> provide Tested-by tag or error report.
> >>>> I did a test run on my WD MyBook Live. I applied all the patches in
> >>>> this series on top of the topic/dw branch of Vinod Koul:
> >>>> <https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>
> >>>>
> >>>> Tested-by: Christian Lamparter<[email protected]>
> >>>> ---
> >>>> results for my old ST3808110AS HDD. filesystem is ext4.
> >>>>
> >>>> # hdparm -t /dev/sda
> >>>>
> >>>> /dev/sda:
> >>>> Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec
> >>>>
> >>>> # bonnie++ -u mbl
> >>>> Using uid:1000, gid:1000.
> >>>> Writing a byte at a time...done
> >>>> Writing intelligently...done
> >>>> Rewriting...done
> >>>> Reading a byte at a time...done
> >>>> Reading intelligently...done
> >>>> start 'em...done...done...done...done...done...
> >>>> Create files in sequential order...done.
> >>>> Stat files in sequential order...done.
> >>>> Delete files in sequential order...done.
> >>>> Create files in random order...done.
> >>>> Stat files in random order...done.
> >>>> Delete files in random order...done.
> >>>> Version 1.97 ------Sequential Output------ --Sequential
> >>>> Input- --Random-
> >>>> Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr-
> >>>> --Block-- --Seeks--
> >>>> Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec
> >>>> %CP /sec %CP
> >>>> mbl 496M 98 99 26011 21 17589 20 538 99 80138
> >>>> 39 208.9 8
> >>>> Latency 95267us 1409ms 295ms 26947us 9644us
> >>>> 1787ms
> >>>> Version 1.97 ------Sequential Create------ --------Random
> >>>> Create--------
> >>>> mbl -Create-- --Read--- -Delete-- -Create--
> >>>> --Read--- -Delete--
> >>>> files /sec %CP /sec %CP /sec %CP /sec %CP /sec
> >>>> %CP /sec %CP
> >>>> 16 6959 78 +++++ +++ 5197 40 7250 79 +++++
> >>>> +++ 4718 37
> >>>> Latency 149ms 6742us 212ms 177ms 767us
> >>>> 217ms
> >>>> 1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms
> >>>>
> >>>>
> >>> Again on copy partitions .
> >> Ok, here's the copy from my mail off-list.
> >>
> >> Well, a unrelated driver "m41t80" caused a crash:
> >> [ 12.912739] Oops: Kernel access of bad area, sig: 11 [#3]
> >> [ 12.912743] PREEMPT Canyonlands
> >> [ 12.912753] CPU: 0 PID: 1413 Comm: irq/45-m41t80 Tainted: G
> >> D 4.6.0-rc4-next-20160421-sam460ex-jm #1
> >> [ 12.912757] task: ea9834e0 ti: eea6c000 task.ti: eea6c000
> >> [ 12.912760] NIP: c0224480 LR: c0023494 CTR: c0042508
> >> [ 12.912764] REGS: eea6daf0 TRAP: 0300 Tainted: G D
> >> (4.6.0-rc4-next-20160421-sam460ex-jm)
> >> [ 12.912774] MSR: 00029000 <CE,EE,ME> CR: 24008282 XER: 00000000
> >> [ 12.912825] DEAR: 00000008 ESR: 00000000
> >> [...]
> >> [ 12.912927] --- interrupt: 300 at mutex_lock+0x0/0x1c
> >> [ 12.912927] LR = m41t80_handle_irq+0x28/0xac
> >> [ 12.912932] [eea6de40] [00000000] (null) (unreliable)
> >> [ 12.912938] [eea6de60] [c004ffac] irq_thread_fn+0x2c/0x48
> >> [ 12.912944] [eea6de80] [c00501cc] irq_thread+0xc4/0x160
> >> [ 12.912951] [eea6ded0] [c003a3f8] kthread+0xc8/0xcc
> >> [ 12.912957] [eea6df40] [c000aee8] ret_from_kernel_thread+0x5c/0x64
> >> [ 12.912960] Instruction dump:
> >> [ 12.912974] 80010014 7fc3f378 bbc10008 7c0803a6 38210010 4be24ca8
> >> 9421ffd0 7c0802a6
> >> [ 12.912987] bf210014 90010034 3b4302d8 812302ec <83890008>
> >> 812302d8 7f9a4840 419e011c
> >> [ 12.912995] Fixing recursive fault but reboot is needed!
> >> ^^^ "reboot is needed!"
> >>
> >> Another thing that came to my mind: Have you checked if your hard drive
> >> and the cables are ok? Are there any pending sectors or suspicious smart
> >> values? Has the drive passed the extended offline test?
> >> Otherwise, I can't reproduce the error with my MyBook system. I've
> >> tested
> >> your kernel and it worked on the device without crashing. (I
> >> copied/dd'ed
> >> 80GB from and back to the hard-drive. It was long and boring, but I
> >> didn't
> >> encounter any issues and the crc32 matched).
> >>
> >> Sorry, but I can't help you if I can't reproduce it... And short of
> >> sending
> >> your box to test, I see no efficient way to debug it. However, what I
> >> can
> >> do, if you are interested: I have a few "build your own" My Book Live
> >> kits.
> >> It just needs a 3.5" hard-drive and 12v power adapter. If you are
> >> interested
> >> PM me off-list, this way you can verify that the kernels you build do
> >> work,
> >> just in case this error is due to a hardware issue (zapped controller,
> >> bad ram/drive/cable?) with your sam460ex box.
> >>
> >> Regards,
> >> Christian
> >>
> >>
> > My Hardware seems ok.
> > I have swapped cables and drives between the SII3512 pci controller
> > and the DWC controller.
> > No issues when connected to the SII3512 pci controller .
> > The DWC controller works ok under AmigaOS 4.1FE so that does not
> > appear to be a problem.
> >
> > Regards
> > Julian
> >
> >
> >
> >
> >
> >
> Test with kernel compiled with no other sata controllers included.
> Freshly formatted harddrive with one ntfs partition. MS-DOs partition
> table.
> Booted from USB thumb drive.
> Keyboard and mouse freeze as soon as gparted is run.
>

Well, then. Have you checked for any errata for the sam460ex?
There's a known errata for the 460EX, with the CPU lockup upon
high AHB traffic:
<http://lists.denx.de/pipermail/u-boot/2008-June/036078.html>

"This patch implements a fix provided by AMCC so that the lockup upon
simultanious traffic on AHB USB OTG, USB 2.0 and SATA doesn't occur
anymore:..."

This should be fixed by u-boot. However, there's no telling if
there's more to this workaround in the dma engine. You could try
to do the testing without anything connected to the USB ports
and disable/remove all usb hcds modules. As for fixing this:
I did a quick search but couldn't find any public information.
There's always [email protected] (contact them!), or maybe someone
from the Amiga community knows more?

2016-04-24 13:06:24

by Julian Margetson

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On 4/23/2016 3:41 PM, Christian Lamparter wrote:
> On Saturday, April 23, 2016 11:44:09 AM Julian Margetson wrote:
>> On 4/23/2016 8:02 AM, Julian Margetson wrote:
>>> On 4/22/2016 7:06 AM, Christian Lamparter wrote:
>>>> On Friday, April 22, 2016 06:50:44 AM Julian Margetson wrote:
>>>>> On 4/21/2016 4:25 PM, Christian Lamparter wrote:
>>>>>> On Thursday, April 21, 2016 09:15:21 PM Andy Shevchenko wrote:
>>>>>>> The last approach in the commit 8b3444852a2b ("sata_dwc_460ex:
>>>>>>> move to generic
>>>>>>> DMA driver") to switch to generic DMA engine API wasn't tested on
>>>>>>> bare metal.
>>>>>>> Besides that we expecting new board support coming with the same
>>>>>>> SATA IP but
>>>>>>> with different DMA.
>>>>>>>
>>>>>>> The driver has been tested myself on Sam460ex and WD MyBookLive
>>>>>>> (apollo3g)
>>>>>>> boards. In any case I ask Christian, M?ns, and Julian to
>>>>>>> independently test and
>>>>>>> provide Tested-by tag or error report.
>>>>>> I did a test run on my WD MyBook Live. I applied all the patches in
>>>>>> this series on top of the topic/dw branch of Vinod Koul:
>>>>>> <https://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/>
>>>>>>
>>>>>> Tested-by: Christian Lamparter<[email protected]>
>>>>>> ---
>>>>>> results for my old ST3808110AS HDD. filesystem is ext4.
>>>>>>
>>>>>> # hdparm -t /dev/sda
>>>>>>
>>>>>> /dev/sda:
>>>>>> Timing buffered disk reads: 204 MB in 3.02 seconds = 67.51 MB/sec
>>>>>>
>>>>>> # bonnie++ -u mbl
>>>>>> Using uid:1000, gid:1000.
>>>>>> Writing a byte at a time...done
>>>>>> Writing intelligently...done
>>>>>> Rewriting...done
>>>>>> Reading a byte at a time...done
>>>>>> Reading intelligently...done
>>>>>> start 'em...done...done...done...done...done...
>>>>>> Create files in sequential order...done.
>>>>>> Stat files in sequential order...done.
>>>>>> Delete files in sequential order...done.
>>>>>> Create files in random order...done.
>>>>>> Stat files in random order...done.
>>>>>> Delete files in random order...done.
>>>>>> Version 1.97 ------Sequential Output------ --Sequential
>>>>>> Input- --Random-
>>>>>> Concurrency 1 -Per Chr- --Block-- -Rewrite- -Per Chr-
>>>>>> --Block-- --Seeks--
>>>>>> Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec
>>>>>> %CP /sec %CP
>>>>>> mbl 496M 98 99 26011 21 17589 20 538 99 80138
>>>>>> 39 208.9 8
>>>>>> Latency 95267us 1409ms 295ms 26947us 9644us
>>>>>> 1787ms
>>>>>> Version 1.97 ------Sequential Create------ --------Random
>>>>>> Create--------
>>>>>> mbl -Create-- --Read--- -Delete-- -Create--
>>>>>> --Read--- -Delete--
>>>>>> files /sec %CP /sec %CP /sec %CP /sec %CP /sec
>>>>>> %CP /sec %CP
>>>>>> 16 6959 78 +++++ +++ 5197 40 7250 79 +++++
>>>>>> +++ 4718 37
>>>>>> Latency 149ms 6742us 212ms 177ms 767us
>>>>>> 217ms
>>>>>> 1.97,1.97,mbl,1,1461269771,496M,,98,99,26011,21,17589,20,538,99,80138,39,208.9,8,16,,,,,6959,78,+++++,+++,5197,40,7250,79,+++++,+++,4718,37,95267us,1409ms,295ms,26947us,9644us,1787ms,149ms,6742us,212ms,177ms,767us,217ms
>>>>>>
>>>>>>
>>>>> Again on copy partitions .
>>>> Ok, here's the copy from my mail off-list.
>>>>
>>>> Well, a unrelated driver "m41t80" caused a crash:
>>>> [ 12.912739] Oops: Kernel access of bad area, sig: 11 [#3]
>>>> [ 12.912743] PREEMPT Canyonlands
>>>> [ 12.912753] CPU: 0 PID: 1413 Comm: irq/45-m41t80 Tainted: G
>>>> D 4.6.0-rc4-next-20160421-sam460ex-jm #1
>>>> [ 12.912757] task: ea9834e0 ti: eea6c000 task.ti: eea6c000
>>>> [ 12.912760] NIP: c0224480 LR: c0023494 CTR: c0042508
>>>> [ 12.912764] REGS: eea6daf0 TRAP: 0300 Tainted: G D
>>>> (4.6.0-rc4-next-20160421-sam460ex-jm)
>>>> [ 12.912774] MSR: 00029000 <CE,EE,ME> CR: 24008282 XER: 00000000
>>>> [ 12.912825] DEAR: 00000008 ESR: 00000000
>>>> [...]
>>>> [ 12.912927] --- interrupt: 300 at mutex_lock+0x0/0x1c
>>>> [ 12.912927] LR = m41t80_handle_irq+0x28/0xac
>>>> [ 12.912932] [eea6de40] [00000000] (null) (unreliable)
>>>> [ 12.912938] [eea6de60] [c004ffac] irq_thread_fn+0x2c/0x48
>>>> [ 12.912944] [eea6de80] [c00501cc] irq_thread+0xc4/0x160
>>>> [ 12.912951] [eea6ded0] [c003a3f8] kthread+0xc8/0xcc
>>>> [ 12.912957] [eea6df40] [c000aee8] ret_from_kernel_thread+0x5c/0x64
>>>> [ 12.912960] Instruction dump:
>>>> [ 12.912974] 80010014 7fc3f378 bbc10008 7c0803a6 38210010 4be24ca8
>>>> 9421ffd0 7c0802a6
>>>> [ 12.912987] bf210014 90010034 3b4302d8 812302ec <83890008>
>>>> 812302d8 7f9a4840 419e011c
>>>> [ 12.912995] Fixing recursive fault but reboot is needed!
>>>> ^^^ "reboot is needed!"
>>>>
>>>> Another thing that came to my mind: Have you checked if your hard drive
>>>> and the cables are ok? Are there any pending sectors or suspicious smart
>>>> values? Has the drive passed the extended offline test?
>>>> Otherwise, I can't reproduce the error with my MyBook system. I've
>>>> tested
>>>> your kernel and it worked on the device without crashing. (I
>>>> copied/dd'ed
>>>> 80GB from and back to the hard-drive. It was long and boring, but I
>>>> didn't
>>>> encounter any issues and the crc32 matched).
>>>>
>>>> Sorry, but I can't help you if I can't reproduce it... And short of
>>>> sending
>>>> your box to test, I see no efficient way to debug it. However, what I
>>>> can
>>>> do, if you are interested: I have a few "build your own" My Book Live
>>>> kits.
>>>> It just needs a 3.5" hard-drive and 12v power adapter. If you are
>>>> interested
>>>> PM me off-list, this way you can verify that the kernels you build do
>>>> work,
>>>> just in case this error is due to a hardware issue (zapped controller,
>>>> bad ram/drive/cable?) with your sam460ex box.
>>>>
>>>> Regards,
>>>> Christian
>>>>
>>>>
>>> My Hardware seems ok.
>>> I have swapped cables and drives between the SII3512 pci controller
>>> and the DWC controller.
>>> No issues when connected to the SII3512 pci controller .
>>> The DWC controller works ok under AmigaOS 4.1FE so that does not
>>> appear to be a problem.
>>>
>>> Regards
>>> Julian
>>>
>>>
>>>
>>>
>>>
>>>
>> Test with kernel compiled with no other sata controllers included.
>> Freshly formatted harddrive with one ntfs partition. MS-DOs partition
>> table.
>> Booted from USB thumb drive.
>> Keyboard and mouse freeze as soon as gparted is run.
>>
> Well, then. Have you checked for any errata for the sam460ex?
> There's a known errata for the 460EX, with the CPU lockup upon
> high AHB traffic:
> <http://lists.denx.de/pipermail/u-boot/2008-June/036078.html>
>
> "This patch implements a fix provided by AMCC so that the lockup upon
> simultanious traffic on AHB USB OTG, USB 2.0 and SATA doesn't occur
> anymore:..."
>
> This should be fixed by u-boot. However, there's no telling if
> there's more to this workaround in the dma engine. You could try
> to do the testing without anything connected to the USB ports
> and disable/remove all usb hcds modules. As for fixing this:
> I did a quick search but couldn't find any public information.
> There's always [email protected] (contact them!), or maybe someone
> from the Amiga community knows more?
>
>

Tested with kernel with all USB disabled.
No sata error messages during the partition copy but the copying is
quite slow .
so this does appear to be the problem .

Regards
Julian


2016-04-24 15:21:33

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On Sunday, April 24, 2016 09:05:43 AM Julian Margetson wrote:
> On 4/23/2016 3:41 PM, Christian Lamparter wrote:
> > There's a known errata for the 460EX, with the CPU lockup upon
> > high AHB traffic:
> > <http://lists.denx.de/pipermail/u-boot/2008-June/036078.html>
> >
> > "This patch implements a fix provided by AMCC so that the lockup upon
> > simultanious traffic on AHB USB OTG, USB 2.0 and SATA doesn't occur
> > anymore:..."
> >
> > This should be fixed by u-boot. However, there's no telling if
> > there's more to this workaround in the dma engine. You could try
> > to do the testing without anything connected to the USB ports
> > and disable/remove all usb hcds modules. As for fixing this:
> > I did a quick search but couldn't find any public information.
> > There's always [email protected] (contact them!), or maybe someone
> > from the Amiga community knows more?
> >
> >
>
> Tested with kernel with all USB disabled. No sata error messages
> during the partition copy but the copying is quite slow.
Ok. The CONFIG_DMADEVICES_DEBUG and CONFIG_DMADEVICES_VDEBUG option
have quite a large overhead, if this fixed the issue for now you
could try to disable them and look if the issue comes back or not.
(also, you can drop the mdelay patch if it's still applied). If
the issue doesn't come back, you could add your "Tested-by" tag
too.

Another thing, the sata dwc driver doesn't yet support NCQ. Do you
know if the driver for the Amiga OS does?

> so this does appear to be the problem.
So, how to fix this? I know, there's an AHB DMA Arbiter. But I can't
get any documentation for it from AMCC/APM. Maybe denx.de or someone
from the Amiga community knows how to deal with it. In theory, we
could try if limiting the burst length, pending dma request count or
add code to retry failed dma transfers and reinit the usb-cores would
help.

Regards,
Christian

2016-04-24 17:52:08

by Julian Margetson

[permalink] [raw]
Subject: Re: [PATCH v1 00/23] ata: sata_dwc_460ex: make it working again

On 4/24/2016 11:21 AM, Christian Lamparter wrote:
> On Sunday, April 24, 2016 09:05:43 AM Julian Margetson wrote:
>> On 4/23/2016 3:41 PM, Christian Lamparter wrote:
>>> There's a known errata for the 460EX, with the CPU lockup upon
>>> high AHB traffic:
>>> <http://lists.denx.de/pipermail/u-boot/2008-June/036078.html>
>>>
>>> "This patch implements a fix provided by AMCC so that the lockup upon
>>> simultanious traffic on AHB USB OTG, USB 2.0 and SATA doesn't occur
>>> anymore:..."
>>>
>>> This should be fixed by u-boot. However, there's no telling if
>>> there's more to this workaround in the dma engine. You could try
>>> to do the testing without anything connected to the USB ports
>>> and disable/remove all usb hcds modules. As for fixing this:
>>> I did a quick search but couldn't find any public information.
>>> There's always [email protected] (contact them!), or maybe someone
>>> from the Amiga community knows more?
>>>
>>>
>> Tested with kernel with all USB disabled. No sata error messages
>> during the partition copy but the copying is quite slow.
> Ok. The CONFIG_DMADEVICES_DEBUG and CONFIG_DMADEVICES_VDEBUG option
> have quite a large overhead, if this fixed the issue for now you
> could try to disable them and look if the issue comes back or not.
> (also, you can drop the mdelay patch if it's still applied). If
> the issue doesn't come back, you could add your "Tested-by" tag
> too.
>
> Another thing, the sata dwc driver doesn't yet support NCQ. Do you
> know if the driver for the Amiga OS does?
>
>> so this does appear to be the problem.
> So, how to fix this? I know, there's an AHB DMA Arbiter. But I can't
> get any documentation for it from AMCC/APM. Maybe denx.de or someone
> from the Amiga community knows how to deal with it. In theory, we
> could try if limiting the burst length, pending dma request count or
> add code to retry failed dma transfers and reinit the usb-cores would
> help.
>
> Regards,
> Christian
>
>
Disabled

CONFIG_DMADEVICES_DEBUG and CONFIG_DMADEVICES_VDEBUG

Still see issues with the USB enabled.
With USB also disabled I was able to finish the partition copy. But
again it is very slow.

(parted) mklabel msdos
Warning: The existing disk label on /dev/sda will be destroyed and all
data on
this disk will be lost. Do you want to continue?
Yes/No? y
(parted) p
Model: ATA WDC WD5000AAKX-0 (scsi)
Disk /dev/sda: 500GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number Start End Size Type File system Flags

(parted) q
Information: You may need to update /etc/fstab.

root@Amigaone:/home/amigaone# dd if=/dev/sdb6 of=/dev/sda
43597824+0 records in
43597824+0 records out
22322085888 bytes (22 GB, 21 GiB) copied, 2825.93 s, 7.9 MB/s

Regards
Julian