From: cbostic@linux.vnet.ibm.com (Christopher Bostic)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v7 17/23] drivers/fsi: Add error handling for slave
Date: Thu, 11 May 2017 16:00:54 -0500 [thread overview]
Message-ID: <20170511210101.78409-18-cbostic@linux.vnet.ibm.com> (raw)
In-Reply-To: <20170511210101.78409-1-cbostic@linux.vnet.ibm.com>
From: Jeremy Kerr <jk@ozlabs.org>
This change implements error handling in the FSI core, by cleaning up
and retrying failed operations, using the SISC, TERM and BREAK
facilities.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
drivers/fsi/fsi-core.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 114 insertions(+), 7 deletions(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index bc73f13..6e7d778 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -46,7 +46,9 @@
/*
* FSI slave engine control register offsets
*/
-#define FSI_SMODE 0x0 /* R/W: Mode register */
+#define FSI_SMODE 0x0 /* R/W: Mode register */
+#define FSI_SISC 0x8 /* R/W: Interrupt condition */
+#define FSI_SSTAT 0x14 /* R : Slave status */
/*
* SMODE fields
@@ -77,10 +79,14 @@ struct fsi_slave {
#define to_fsi_master(d) container_of(d, struct fsi_master, dev)
#define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
+static const int slave_retries = 2;
+static int discard_errors;
+
static int fsi_master_read(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, void *val, size_t size);
static int fsi_master_write(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, const void *val, size_t size);
+static int fsi_master_break(struct fsi_master *master, int link);
/*
* fsi_device_read() / fsi_device_write() / fsi_device_peek()
@@ -173,32 +179,131 @@ static int fsi_slave_calc_addr(struct fsi_slave *slave, uint32_t *addrp,
return 0;
}
+int fsi_slave_report_and_clear_errors(struct fsi_slave *slave)
+{
+ struct fsi_master *master = slave->master;
+ uint32_t irq, stat;
+ int rc, link;
+ uint8_t id;
+
+ link = slave->link;
+ id = slave->id;
+
+ rc = fsi_master_read(master, link, id, FSI_SLAVE_BASE + FSI_SISC,
+ &irq, sizeof(irq));
+ if (rc)
+ return rc;
+
+ rc = fsi_master_read(master, link, id, FSI_SLAVE_BASE + FSI_SSTAT,
+ &stat, sizeof(stat));
+ if (rc)
+ return rc;
+
+ dev_info(&slave->dev, "status: 0x%08x, sisc: 0x%08x\n",
+ be32_to_cpu(stat), be32_to_cpu(irq));
+
+ /* clear interrupts */
+ return fsi_master_write(master, link, id, FSI_SLAVE_BASE + FSI_SISC,
+ &irq, sizeof(irq));
+}
+
+static int fsi_slave_set_smode(struct fsi_master *master, int link, int id);
+
+int fsi_slave_handle_error(struct fsi_slave *slave, bool write, uint32_t addr,
+ size_t size)
+{
+ struct fsi_master *master = slave->master;
+ int rc, link;
+ uint32_t reg;
+ uint8_t id;
+
+ if (discard_errors)
+ return -1;
+
+ link = slave->link;
+ id = slave->id;
+
+ dev_dbg(&slave->dev, "handling error on %s to 0x%08x[%zd]",
+ write ? "write" : "read", addr, size);
+
+ /* try a simple clear of error conditions, which may fail if we've lost
+ * communication with the slave
+ */
+ rc = fsi_slave_report_and_clear_errors(slave);
+ if (!rc)
+ return 0;
+
+ /* send a TERM and retry */
+ if (master->term) {
+ rc = master->term(master, link, id);
+ if (!rc) {
+ rc = fsi_master_read(master, link, id, 0,
+ ®, sizeof(reg));
+ if (!rc)
+ rc = fsi_slave_report_and_clear_errors(slave);
+ if (!rc)
+ return 0;
+ }
+ }
+
+ /* getting serious, reset the slave via BREAK */
+ rc = fsi_master_break(master, link);
+ if (rc)
+ return rc;
+
+ rc = fsi_slave_set_smode(master, link, id);
+ if (rc)
+ return rc;
+
+ return fsi_slave_report_and_clear_errors(slave);
+}
+
int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
void *val, size_t size)
{
uint8_t id = slave->id;
- int rc;
+ int rc, err_rc, i;
rc = fsi_slave_calc_addr(slave, &addr, &id);
if (rc)
return rc;
- return fsi_master_read(slave->master, slave->link, id,
- addr, val, size);
+ for (i = 0; i < slave_retries; i++) {
+ rc = fsi_master_read(slave->master, slave->link,
+ id, addr, val, size);
+ if (!rc)
+ break;
+
+ err_rc = fsi_slave_handle_error(slave, false, addr, size);
+ if (err_rc)
+ break;
+ }
+
+ return rc;
}
int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
const void *val, size_t size)
{
uint8_t id = slave->id;
- int rc;
+ int rc, err_rc, i;
rc = fsi_slave_calc_addr(slave, &addr, &id);
if (rc)
return rc;
- return fsi_master_write(slave->master, slave->link, id,
- addr, val, size);
+ for (i = 0; i < slave_retries; i++) {
+ rc = fsi_master_write(slave->master, slave->link,
+ id, addr, val, size);
+ if (!rc)
+ break;
+
+ err_rc = fsi_slave_handle_error(slave, true, addr, size);
+ if (err_rc)
+ break;
+ }
+
+ return rc;
}
extern int fsi_slave_claim_range(struct fsi_slave *slave,
@@ -766,3 +871,5 @@ static void fsi_exit(void)
module_init(fsi_init);
module_exit(fsi_exit);
+module_param(discard_errors, int, 0664);
+MODULE_PARM_DESC(discard_errors, "Don't invoke error handling on bus accesses");
--
1.8.2.2
WARNING: multiple messages have this Message-ID (diff)
From: Christopher Bostic <cbostic@linux.vnet.ibm.com>
To: robh+dt@kernel.org, mark.rutland@arm.com, linux@armlinux.org.uk,
rostedt@goodmis.org, mingo@redhat.com,
gregkh@linuxfoundation.org, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Cc: Jeremy Kerr <jk@ozlabs.org>,
joel@jms.id.au, linux-kernel@vger.kernel.org, andrew@aj.id.au,
alistair@popple.id.au, benh@kernel.crashing.org,
Christopher Bostic <cbostic@linux.vnet.ibm.com>
Subject: [PATCH v7 17/23] drivers/fsi: Add error handling for slave
Date: Thu, 11 May 2017 16:00:54 -0500 [thread overview]
Message-ID: <20170511210101.78409-18-cbostic@linux.vnet.ibm.com> (raw)
In-Reply-To: <20170511210101.78409-1-cbostic@linux.vnet.ibm.com>
From: Jeremy Kerr <jk@ozlabs.org>
This change implements error handling in the FSI core, by cleaning up
and retrying failed operations, using the SISC, TERM and BREAK
facilities.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
drivers/fsi/fsi-core.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 114 insertions(+), 7 deletions(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index bc73f13..6e7d778 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -46,7 +46,9 @@
/*
* FSI slave engine control register offsets
*/
-#define FSI_SMODE 0x0 /* R/W: Mode register */
+#define FSI_SMODE 0x0 /* R/W: Mode register */
+#define FSI_SISC 0x8 /* R/W: Interrupt condition */
+#define FSI_SSTAT 0x14 /* R : Slave status */
/*
* SMODE fields
@@ -77,10 +79,14 @@ struct fsi_slave {
#define to_fsi_master(d) container_of(d, struct fsi_master, dev)
#define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
+static const int slave_retries = 2;
+static int discard_errors;
+
static int fsi_master_read(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, void *val, size_t size);
static int fsi_master_write(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, const void *val, size_t size);
+static int fsi_master_break(struct fsi_master *master, int link);
/*
* fsi_device_read() / fsi_device_write() / fsi_device_peek()
@@ -173,32 +179,131 @@ static int fsi_slave_calc_addr(struct fsi_slave *slave, uint32_t *addrp,
return 0;
}
+int fsi_slave_report_and_clear_errors(struct fsi_slave *slave)
+{
+ struct fsi_master *master = slave->master;
+ uint32_t irq, stat;
+ int rc, link;
+ uint8_t id;
+
+ link = slave->link;
+ id = slave->id;
+
+ rc = fsi_master_read(master, link, id, FSI_SLAVE_BASE + FSI_SISC,
+ &irq, sizeof(irq));
+ if (rc)
+ return rc;
+
+ rc = fsi_master_read(master, link, id, FSI_SLAVE_BASE + FSI_SSTAT,
+ &stat, sizeof(stat));
+ if (rc)
+ return rc;
+
+ dev_info(&slave->dev, "status: 0x%08x, sisc: 0x%08x\n",
+ be32_to_cpu(stat), be32_to_cpu(irq));
+
+ /* clear interrupts */
+ return fsi_master_write(master, link, id, FSI_SLAVE_BASE + FSI_SISC,
+ &irq, sizeof(irq));
+}
+
+static int fsi_slave_set_smode(struct fsi_master *master, int link, int id);
+
+int fsi_slave_handle_error(struct fsi_slave *slave, bool write, uint32_t addr,
+ size_t size)
+{
+ struct fsi_master *master = slave->master;
+ int rc, link;
+ uint32_t reg;
+ uint8_t id;
+
+ if (discard_errors)
+ return -1;
+
+ link = slave->link;
+ id = slave->id;
+
+ dev_dbg(&slave->dev, "handling error on %s to 0x%08x[%zd]",
+ write ? "write" : "read", addr, size);
+
+ /* try a simple clear of error conditions, which may fail if we've lost
+ * communication with the slave
+ */
+ rc = fsi_slave_report_and_clear_errors(slave);
+ if (!rc)
+ return 0;
+
+ /* send a TERM and retry */
+ if (master->term) {
+ rc = master->term(master, link, id);
+ if (!rc) {
+ rc = fsi_master_read(master, link, id, 0,
+ ®, sizeof(reg));
+ if (!rc)
+ rc = fsi_slave_report_and_clear_errors(slave);
+ if (!rc)
+ return 0;
+ }
+ }
+
+ /* getting serious, reset the slave via BREAK */
+ rc = fsi_master_break(master, link);
+ if (rc)
+ return rc;
+
+ rc = fsi_slave_set_smode(master, link, id);
+ if (rc)
+ return rc;
+
+ return fsi_slave_report_and_clear_errors(slave);
+}
+
int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
void *val, size_t size)
{
uint8_t id = slave->id;
- int rc;
+ int rc, err_rc, i;
rc = fsi_slave_calc_addr(slave, &addr, &id);
if (rc)
return rc;
- return fsi_master_read(slave->master, slave->link, id,
- addr, val, size);
+ for (i = 0; i < slave_retries; i++) {
+ rc = fsi_master_read(slave->master, slave->link,
+ id, addr, val, size);
+ if (!rc)
+ break;
+
+ err_rc = fsi_slave_handle_error(slave, false, addr, size);
+ if (err_rc)
+ break;
+ }
+
+ return rc;
}
int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
const void *val, size_t size)
{
uint8_t id = slave->id;
- int rc;
+ int rc, err_rc, i;
rc = fsi_slave_calc_addr(slave, &addr, &id);
if (rc)
return rc;
- return fsi_master_write(slave->master, slave->link, id,
- addr, val, size);
+ for (i = 0; i < slave_retries; i++) {
+ rc = fsi_master_write(slave->master, slave->link,
+ id, addr, val, size);
+ if (!rc)
+ break;
+
+ err_rc = fsi_slave_handle_error(slave, true, addr, size);
+ if (err_rc)
+ break;
+ }
+
+ return rc;
}
extern int fsi_slave_claim_range(struct fsi_slave *slave,
@@ -766,3 +871,5 @@ static void fsi_exit(void)
module_init(fsi_init);
module_exit(fsi_exit);
+module_param(discard_errors, int, 0664);
+MODULE_PARM_DESC(discard_errors, "Don't invoke error handling on bus accesses");
--
1.8.2.2
next prev parent reply other threads:[~2017-05-11 21:00 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-11 21:00 [PATCH v7 00/23] FSI device driver implementation Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 01/23] drivers/fsi: Add fsi master definition Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 02/23] drivers/fsi: Add slave definition Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 03/23] drivers/fsi: Add empty master scan Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 04/23] lib: Add crc4 module Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 05/23] drivers/fsi: Add slave & master read/write APIs Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 06/23] drivers/fsi: Set up links for slave communication Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 07/23] drivers/fsi: Implement slave initialisation Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 08/23] drivers/fsi: Set slave SMODE to init communication Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 09/23] drivers/fsi: scan slaves & register devices Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 10/23] drivers/fsi: Add device read/write/peek API Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 11/23] drivers/fsi: Add master unscan Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 12/23] drivers/fsi: Add documentation for GPIO bindings Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 13/23] drivers/fsi: Add client driver register utilities Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 14/23] drivers/fsi: Add sysfs files for FSI master & slave accesses Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 15/23] drivers/fsi: expose direct-access slave API Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 16/23] drivers/fsi: Add tracepoints for low-level operations Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic [this message]
2017-05-11 21:00 ` [PATCH v7 17/23] drivers/fsi: Add error handling for slave Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 18/23] drivers/fsi: Document FSI master sysfs files in ABI Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 19/23] drivers/fsi: Add GPIO based FSI master Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 20/23] drivers/fsi/gpio: Add tracepoints for GPIO master Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 21/23] drivers/fsi: Add SCOM FSI client device driver Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:00 ` [PATCH v7 22/23] drivers/fsi: Add hub master support Christopher Bostic
2017-05-11 21:00 ` Christopher Bostic
2017-05-11 21:01 ` [PATCH v7 23/23] drivers/fsi: Use asynchronous slave mode Christopher Bostic
2017-05-11 21:01 ` Christopher Bostic
2017-05-31 17:17 ` [PATCH v7 00/23] FSI device driver implementation Christopher Bostic
2017-05-31 17:17 ` Christopher Bostic
2017-05-31 17:17 ` Christopher Bostic
2017-06-03 10:05 ` Greg KH
2017-06-03 10:05 ` Greg KH
2017-06-03 10:05 ` Greg KH
2017-06-03 21:25 ` Steven Rostedt
2017-06-03 21:25 ` Steven Rostedt
2017-06-03 21:25 ` Steven Rostedt
2017-06-05 19:21 ` Christopher Bostic
2017-06-05 19:21 ` Christopher Bostic
2017-06-05 19:21 ` Christopher Bostic
2017-06-05 19:20 ` Christopher Bostic
2017-06-05 19:20 ` Christopher Bostic
2017-06-05 19:20 ` Christopher Bostic
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170511210101.78409-18-cbostic@linux.vnet.ibm.com \
--to=cbostic@linux.vnet.ibm.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.