All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master
@ 2017-02-21 21:50 Christopher Bostic
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect Christopher Bostic
                   ` (8 more replies)
  0 siblings, 9 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Adds the FSI hub master functionality to the OpenFSI device driver.
Hub master is a FSI client device driver that registers with the
core and is notified when devices it wants, hub master engine and
links, are discovered.

v2: Restructured to move hub into the core instead of a separate
    slave device driver.

Christopher Bostic (7):
  drivers/fsi: Add hub master scan detect
  drivers/fsi: Initialize hub master
  drivers/fsi: Define hub master callbacks
  drivers/fsi: Move common read write ops into single function
  drivers/fsi: Add retry on bus error detect
  drivers/fsi: Cleanup bus errors
  tools/testing/selftests: Add fsi command line tool


-- 
1.8.2.2

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
@ 2017-02-21 21:50 ` Christopher Bostic
  2017-02-22  1:02   ` Jeremy Kerr
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 2/7] drivers/fsi: Initialize hub master Christopher Bostic
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

On detect of hub master engine in config space set up a master
device and register it with the core.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>

---

Changes in V2:

- Refactor structures for hub master. Previously hub master engine
  was considered a slave engine.
---
 drivers/fsi/fsi-core.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index d63a892..646bb43 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -43,6 +43,11 @@
 
 #define FSI_IPOLL_PERIOD		msecs_to_jiffies(fsi_ipoll_period_ms)
 
+#define	FSI_ENGID_HUB_MASTER		0x1c
+#define	FSI_ENGID_HUB_LINK		0x1d
+#define	FSI_HUB_LINK_OFFSET		0x80000
+#define	FSI_HUB_MASTER_MAX_LINKS	8
+
 static const int engine_page_size = 0x400;
 static struct task_struct *master_ipoll;
 static unsigned int fsi_ipoll_period_ms = 100;
@@ -58,6 +63,14 @@ struct fsi_slave {
 	uint8_t			id;
 };
 
+struct fsi_master_hub {
+	struct fsi_master	master;
+	struct fsi_slave	*slave;
+	uint32_t		control_regs;	/* slave-relative addr regs */
+	uint32_t		base;		/* slave-relative addr of */
+						/* master address space */
+};
+
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
 static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
@@ -203,12 +216,18 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 			slave->id, addr, val, size);
 }
 
+static int hub_master_init(struct fsi_master_hub *hub)
+{
+	return 0;
+}
+
 static int fsi_slave_scan(struct fsi_slave *slave)
 {
 	uint32_t engine_addr;
 	uint32_t conf;
 	int rc, i;
 	uint8_t si1s_bit = 1;
+	struct fsi_master_hub *hub;
 
 	INIT_LIST_HEAD(&slave->my_engines);
 
@@ -252,7 +271,31 @@ static int fsi_slave_scan(struct fsi_slave *slave)
 		 * Unused address areas are marked by a zero type value; this
 		 * skips the defined address areas
 		 */
-		if (type != 0 && slots != 0) {
+		if (type != 0) {
+
+			if (type == FSI_ENGID_HUB_MASTER) {
+				hub = kzalloc(sizeof(*hub), GFP_KERNEL);
+				if (!hub)
+					return -ENOMEM;
+
+				hub->base = FSI_HUB_LINK_OFFSET;
+				hub->control_regs = engine_addr;
+				hub->slave = slave;
+				rc = hub_master_init(hub);
+
+				continue;
+			}
+			if (type == FSI_ENGID_HUB_LINK) {
+				if (!hub)
+					continue;
+
+				hub->master.n_links++;
+				if (hub->master.n_links ==
+						(FSI_HUB_MASTER_MAX_LINKS * 2))
+					rc = fsi_master_register(&hub->master);
+
+				continue;
+			}
 
 			/* create device */
 			dev = fsi_create_device(slave);
@@ -597,7 +640,7 @@ DEVICE_ATTR(fsi_ipoll_period, S_IRUGO | S_IWUSR, fsi_ipoll_period_show,
 
 int fsi_master_register(struct fsi_master *master)
 {
-	if (!master || !master->dev)
+	if (!master)
 		return -EINVAL;
 
 	master->idx = ida_simple_get(&master_ida, 0, INT_MAX, GFP_KERNEL);
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH linux dev-4.7 v2 2/7] drivers/fsi: Initialize hub master
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect Christopher Bostic
@ 2017-02-21 21:50 ` Christopher Bostic
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 3/7] drivers/fsi: Define hub master callbacks Christopher Bostic
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Initialize the hub master control registers.  Set up clock delays,
error handling behavior, toggle link enables.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>

---

Changes in V2:

- Add some description of what a hub master is and how it differs
  from a cascaded master.
---
 drivers/fsi/fsi-core.c   | 116 ++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/fsi/fsi-master.h |  57 +++++++++++++++++++++++
 2 files changed, 172 insertions(+), 1 deletion(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 646bb43..4199188 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
+#include <linux/delay.h>
 
 #include "fsi-master.h"
 
@@ -216,11 +217,124 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 			slave->id, addr, val, size);
 }
 
-static int hub_master_init(struct fsi_master_hub *hub)
+/*
+ * FSI hub master support
+ *
+ * A hub master increases the number of potential target devices that the
+ * primary FSI master can access.  For each link a primary master supports
+ * each of those links can in turn be chained to a hub master with multiple
+ * hub links of its own.  Hubs differ from cascaded masters (cMFSI) in the
+ * total addressable range per link -hubs having address ranges that are much
+ * larger.
+ */
+int hub_master_read(struct fsi_master *master, int linkno, uint8_t slave,
+			uint32_t addr, void *val, size_t size)
+{
+	return 0;
+}
+
+int hub_master_write(struct fsi_master *master, int linkno, uint8_t slave,
+			uint32_t addr, const void *val, size_t size)
 {
 	return 0;
 }
 
+int hub_master_break(struct fsi_master *master, int linkno)
+{
+	return 0;
+}
+
+int hub_master_link_enable(struct fsi_master *master, int linkno)
+{
+	return 0;
+}
+
+static int hub_master_init(struct fsi_master_hub *hub)
+{
+	int rc;
+	uint32_t mver;
+	struct fsi_master *master = &hub->master;
+
+	master->read = hub_master_read;
+	master->write = hub_master_write;
+	master->send_break = hub_master_break;
+	master->link_enable = hub_master_link_enable;
+
+	/* Initialize the MFSI (hub master) engine */
+	rc = fsi_slave_read(hub->slave, hub->control_regs + FSI_MVER, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	mver = FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK
+			| FSI_MRESP_RST_MCR | FSI_MRESP_RST_PYE;
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MRESP0, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	mver = FSI_MECTRL_EOAE | FSI_MECTRL_P8_AUTO_TERM;
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MECTRL, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	mver = FSI_MMODE_EIP | FSI_MMODE_ECRC | FSI_MMODE_EPC
+			| fsi_mmode_crs0(1) | fsi_mmode_crs1(1)
+			| FSI_MMODE_P8_TO_LSB;
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MMODE, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	mver = 0xffff0000;
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MDLYR, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	mver = ~0;
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MSENP0, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	/* Leave enabled long enough for master logic to set up */
+	udelay(1000);
+
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MCENP0, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	rc = fsi_slave_read(hub->slave, hub->control_regs + FSI_MAEB, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	mver = FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK;
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MRESP0, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	rc = fsi_slave_read(hub->slave, hub->control_regs + FSI_MLEVP0, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	/* Reset the master bridge */
+	mver = FSI_MRESB_RST_GEN;
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MRESB0, &mver,
+				sizeof(mver));
+	if (rc)
+		return rc;
+
+	mver = FSI_MRESB_RST_ERR;
+	return fsi_slave_write(hub->slave, hub->control_regs + FSI_MRESB0,
+				&mver, sizeof(mver));
+}
+
 static int fsi_slave_scan(struct fsi_slave *slave)
 {
 	uint32_t engine_addr;
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index 3737404..4a3176b 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -19,6 +19,52 @@
 
 #include <linux/device.h>
 
+/* Control Registers */
+#define FSI_MMODE		0x0		/* R/W: mode */
+#define FSI_MDLYR		0x4		/* R/W: delay */
+#define FSI_MCRSP		0x8		/* R/W: clock rate */
+#define FSI_MENP0		0x10		/* R/W: enable */
+#define FSI_MLEVP0		0x18		/* R: plug detect */
+#define FSI_MSENP0		0x18		/* S: Set enable */
+#define FSI_MCENP0		0x20		/* C: Clear enable */
+#define FSI_MAEB		0x70		/* R: Error address */
+#define FSI_MVER		0x74		/* R: master version/type */
+#define FSI_MRESP0		0xd0		/* W: Port reset */
+#define FSI_MESRB0		0x1d0		/* R: Master error status */
+#define FSI_MRESB0		0x1d0		/* W: Reset bridge */
+#define FSI_MECTRL		0x2e0		/* W: Error control */
+
+/* MMODE: Mode control */
+#define FSI_MMODE_EIP		0x80000000	/* Enable interrupt polling */
+#define FSI_MMODE_ECRC		0x40000000	/* Enable error recovery */
+#define FSI_MMODE_EPC		0x10000000	/* Enable parity checking */
+#define FSI_MMODE_P8_TO_LSB	0x00000010	/* Timeout value LSB */
+						/* Rolf Fritz Nov 20, 2013: */
+						/*   MSB=1, LSB=0 is 0.8 ms */
+						/*   MSB=0, LSB=1 is 0.9 ms */
+#define FSI_MMODE_CRS0SHFT	18		/* Clk rate selection 0 shift */
+#define FSI_MMODE_CRS0MASK	0x3ff		/* Clk rate selection 0 mask */
+#define FSI_MMODE_CRS1SHFT	8		/* Clk rate selection 1 shift */
+#define FSI_MMODE_CRS1MASK	0x3ff		/* Clk rate selection 1 mask */
+
+/* MRESB: Reset brindge */
+#define FSI_MRESB_RST_GEN	0x80000000	/* General reset */
+#define FSI_MRESB_RST_ERR	0x40000000	/* Error Reset */
+
+/* MRESB: Reset port */
+#define FSI_MRESP_RST_ALL_MASTER 0x20000000	/* Reset all FSI masters */
+#define FSI_MRESP_RST_ALL_LINK	0x10000000	/* Reset all FSI port contr. */
+#define FSI_MRESP_RST_MCR	0x08000000	/* Reset FSI master reg. */
+#define FSI_MRESP_RST_PYE	0x04000000	/* Reset FSI parity error */
+#define FSI_MRESP_RST_ALL	0xfc000000	/* Reset any error */
+
+/* MECTRL: Error control */
+#define FSI_MECTRL_EOAE		0x8000		/* Enable machine check when */
+						/* master 0 in error */
+#define FSI_MECTRL_P8_AUTO_TERM	0x4000		/* Auto terminate */
+
+#define L_MSB_MASK(x)		(0x80000000 >> (x))
+
 struct fsi_master {
 	struct list_head my_slaves;
 	bool		slave_list;
@@ -61,4 +107,15 @@ extern int fsi_master_start_ipoll(struct fsi_master *master);
  */
 uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits);
 
+/* mmode encoders */
+static inline u32 fsi_mmode_crs0(u32 x)
+{
+	return (x & FSI_MMODE_CRS0MASK) << FSI_MMODE_CRS0SHFT;
+}
+
+static inline u32 fsi_mmode_crs1(u32 x)
+{
+	return (x & FSI_MMODE_CRS1MASK) << FSI_MMODE_CRS1SHFT;
+}
+
 #endif /* DRIVERS_FSI_MASTER_H */
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH linux dev-4.7 v2 3/7] drivers/fsi: Define hub master callbacks
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect Christopher Bostic
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 2/7] drivers/fsi: Initialize hub master Christopher Bostic
@ 2017-02-21 21:50 ` Christopher Bostic
  2017-02-22  1:06   ` Jeremy Kerr
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 4/7] drivers/fsi: Move common read write ops into single function Christopher Bostic
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Define hub master read, write, link enable, and break ops.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 4199188..360c02a 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -27,6 +27,7 @@
 #define DEBUG
 
 #define FSI_N_SLAVES	4
+#define FSI_BREAK	0xc0de0000
 
 #define FSI_SLAVE_CONF_NEXT_MASK	0x80000000
 #define FSI_SLAVE_CONF_SLOTS_MASK	0x00ff0000
@@ -47,6 +48,7 @@
 #define	FSI_ENGID_HUB_MASTER		0x1c
 #define	FSI_ENGID_HUB_LINK		0x1d
 #define	FSI_HUB_LINK_OFFSET		0x80000
+#define	FSI_MASTER_HUB_LINK_SIZE	0x80000
 #define	FSI_HUB_MASTER_MAX_LINKS	8
 
 static const int engine_page_size = 0x400;
@@ -72,6 +74,7 @@ struct fsi_master_hub {
 						/* master address space */
 };
 
+#define to_fsi_master_hub(d) container_of(d, struct fsi_master_hub, master)
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
 static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
@@ -230,23 +233,47 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 int hub_master_read(struct fsi_master *master, int linkno, uint8_t slave,
 			uint32_t addr, void *val, size_t size)
 {
-	return 0;
+	struct fsi_master_hub *hub = to_fsi_master_hub(master);
+
+	addr += (linkno * FSI_MASTER_HUB_LINK_SIZE) + hub->base;
+	return fsi_slave_read(hub->slave, addr, val, size);
 }
 
 int hub_master_write(struct fsi_master *master, int linkno, uint8_t slave,
 			uint32_t addr, const void *val, size_t size)
 {
-	return 0;
+	struct fsi_master_hub *hub = to_fsi_master_hub(master);
+
+	addr += (linkno * FSI_MASTER_HUB_LINK_SIZE) + hub->base;
+	return fsi_slave_write(hub->slave, addr, val, size);
 }
 
 int hub_master_break(struct fsi_master *master, int linkno)
 {
-	return 0;
+	struct fsi_master_hub *hub = to_fsi_master_hub(master);
+	uint32_t command;
+	uint32_t break_offset = 0x4; /* hw workaround */
+	uint32_t addr;
+
+	command = FSI_BREAK;
+	addr = (linkno * FSI_MASTER_HUB_LINK_SIZE) + hub->base;
+	return fsi_slave_write(hub->slave, addr + break_offset, &command,
+			sizeof(command));
 }
 
 int hub_master_link_enable(struct fsi_master *master, int linkno)
 {
-	return 0;
+	struct fsi_master_hub *hub = to_fsi_master_hub(master);
+	uint32_t menp = L_MSB_MASK(linkno);
+	int rc;
+
+	rc = fsi_slave_write(hub->slave, hub->control_regs + FSI_MSENP0, &menp,
+				sizeof(menp));
+
+	/* Wait for hw to finish enable */
+	mdelay(10);
+
+	return rc;
 }
 
 static int hub_master_init(struct fsi_master_hub *hub)
@@ -571,6 +598,7 @@ static int fsi_slave_init(struct fsi_master *master,
 	slave->id = slave_id;
 	slave->dev.parent = master->dev;
 	slave->dev.release = fsi_slave_release;
+	slave->link = link;
 
 	dev_set_name(&slave->dev, "slave@%02x:%02x", link, slave_id);
 	rc = device_register(&slave->dev);
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH linux dev-4.7 v2 4/7] drivers/fsi: Move common read write ops into single function
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
                   ` (2 preceding siblings ...)
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 3/7] drivers/fsi: Define hub master callbacks Christopher Bostic
@ 2017-02-21 21:50 ` Christopher Bostic
  2017-02-22  1:02   ` Joel Stanley
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect Christopher Bostic
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Move common operations between gpio reads/writes into a new
utility send_command.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>

---

v2: Separate the break out of common read/write elements into its
    own separate patch.
---
 drivers/fsi/fsi-master-gpio.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index 3ed82ea..8aec538 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -354,26 +354,34 @@ static void build_abs_ar_command(struct fsi_gpio_msg *cmd, uint64_t mode,
 	cmd->msg >>= (64 - cmd->bits);
 }
 
+static int send_command(struct fsi_master_gpio *master,
+			struct fsi_gpio_msg *cmd, uint8_t expected,
+			size_t size, void *val)
+{
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
+	serial_out(master, cmd);
+	echo_delay(master);
+	rc = poll_for_response(master, expected, size, val);
+	spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
+
+	return rc;
+}
+
 static int fsi_master_gpio_read(struct fsi_master *_master, int link,
 		uint8_t slave, uint32_t addr, void *val, size_t size)
 {
 	struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
 	struct fsi_gpio_msg cmd;
 	int rc;
-	unsigned long flags;
 
 	if (link != 0)
 		return -ENODEV;
 
 	build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
-
-	spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
-	serial_out(master, &cmd);
-	echo_delay(master);
-	rc = poll_for_response(master, FSI_GPIO_RESP_ACKD, size, val);
-	spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
-
-	return rc;
+	return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
 }
 
 static int fsi_master_gpio_write(struct fsi_master *_master, int link,
@@ -382,20 +390,12 @@ static int fsi_master_gpio_write(struct fsi_master *_master, int link,
 	struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
 	struct fsi_gpio_msg cmd;
 	int rc;
-	unsigned long flags;
 
 	if (link != 0)
 		return -ENODEV;
 
 	build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
-
-	spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
-	serial_out(master, &cmd);
-	echo_delay(master);
-	rc = poll_for_response(master, FSI_GPIO_RESP_ACK, size, NULL);
-	spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
-
-	return rc;
+	return send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
 }
 
 /*
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
                   ` (3 preceding siblings ...)
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 4/7] drivers/fsi: Move common read write ops into single function Christopher Bostic
@ 2017-02-21 21:50 ` Christopher Bostic
  2017-02-22  1:00   ` Joel Stanley
  2017-02-22  1:13   ` Jeremy Kerr
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 6/7] drivers/fsi: Cleanup bus errors Christopher Bostic
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

After each gpio master read/write check for bus errors.  If
errors detected then clean it up and retry the original operation
again.  If second attempt succeeds then don't report original
error to caller.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c        |  4 ++++
 drivers/fsi/fsi-master-gpio.c | 24 ++++++++++++++++++++++--
 drivers/fsi/fsi-master.h      |  3 +++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 360c02a..428675f 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -639,6 +639,10 @@ static int fsi_master_break(struct fsi_master *master, int link)
 	return 0;
 }
 
+void fsi_master_handle_error(struct fsi_master *master, uint32_t addr)
+{
+}
+
 static int fsi_master_scan(struct fsi_master *master)
 {
 	int link, slave_id, rc;
diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index 8aec538..5b502eb 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -381,7 +381,17 @@ static int fsi_master_gpio_read(struct fsi_master *_master, int link,
 		return -ENODEV;
 
 	build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
-	return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
+	rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
+	if (rc) {
+		fsi_master_handle_error(&master->master, addr);
+
+		/* Try again */
+		rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
+		if (rc)
+			fsi_master_handle_error(&master->master, addr);
+	}
+
+	return rc;
 }
 
 static int fsi_master_gpio_write(struct fsi_master *_master, int link,
@@ -395,7 +405,17 @@ static int fsi_master_gpio_write(struct fsi_master *_master, int link,
 		return -ENODEV;
 
 	build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
-	return send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
+	rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
+	if (rc) {
+		fsi_master_handle_error(&master->master, addr);
+
+		/* Try again */
+		rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
+		if (rc)
+			fsi_master_handle_error(&master->master, addr);
+	}
+
+	return rc;
 }
 
 /*
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index 4a3176b..4ed416c 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -19,6 +19,8 @@
 
 #include <linux/device.h>
 
+#include "fsi-master.h"
+
 /* Control Registers */
 #define FSI_MMODE		0x0		/* R/W: mode */
 #define FSI_MDLYR		0x4		/* R/W: delay */
@@ -85,6 +87,7 @@ struct fsi_master {
 extern int fsi_master_register(struct fsi_master *master);
 extern void fsi_master_unregister(struct fsi_master *master);
 extern int fsi_master_start_ipoll(struct fsi_master *master);
+extern void fsi_master_handle_error(struct fsi_master *master, uint32_t addr);
 
 /**
  * crc4 helper: Given a starting crc4 state @c, calculate the crc4 vaue of @x,
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH linux dev-4.7 v2 6/7] drivers/fsi: Cleanup bus errors
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
                   ` (4 preceding siblings ...)
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect Christopher Bostic
@ 2017-02-21 21:50 ` Christopher Bostic
  2017-02-22 21:55   ` Jeremy Kerr
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 7/7] tools/testing/selftests: Add fsi command line tool Christopher Bostic
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Define the bus error cleanup method for primary and hub links.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>

---

v2: Change to atomic operation when checking for nested error
    handling.

    Move slave access details out of gpio master and into the
    core.

    Only allow hub link 1 scans to cut down on scan bus errors.
---
 drivers/fsi/fsi-core.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 428675f..b660d33 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/delay.h>
+#include <linux/bitops.h>
 
 #include "fsi-master.h"
 
@@ -42,6 +43,9 @@
 
 #define FSI_PEEK_BASE			0x410
 #define	FSI_SLAVE_BASE			0x800
+#define	FSI_HUB_CONTROL			0x3400
+
+#define	FSI_SLAVE_SMODE_DFLT		0xa0ff0100
 
 #define FSI_IPOLL_PERIOD		msecs_to_jiffies(fsi_ipoll_period_ms)
 
@@ -54,6 +58,10 @@
 static const int engine_page_size = 0x400;
 static struct task_struct *master_ipoll;
 static unsigned int fsi_ipoll_period_ms = 100;
+static unsigned long fsi_state;
+
+/* state flags */
+#define	FSI_IN_ERR_CLEANUP		0
 
 static DEFINE_IDA(master_ida);
 
@@ -255,6 +263,10 @@ int hub_master_break(struct fsi_master *master, int linkno)
 	uint32_t break_offset = 0x4; /* hw workaround */
 	uint32_t addr;
 
+	/* config table lists 2 entries per hub link */
+	if (linkno >= (master->n_links / 2))
+		return -ENODEV;
+
 	command = FSI_BREAK;
 	addr = (linkno * FSI_MASTER_HUB_LINK_SIZE) + hub->base;
 	return fsi_slave_write(hub->slave, addr + break_offset, &command,
@@ -641,6 +653,28 @@ static int fsi_master_break(struct fsi_master *master, int link)
 
 void fsi_master_handle_error(struct fsi_master *master, uint32_t addr)
 {
+	uint32_t smode = FSI_SLAVE_SMODE_DFLT;
+
+	/* Avoid nested error handling */
+	if (test_and_set_bit(FSI_IN_ERR_CLEANUP, &fsi_state))
+		return;
+
+	fsi_master_break(master, 0);
+	udelay(200);
+	master->write(master, 0, 0, FSI_SLAVE_BASE + FSI_SMODE, &smode,
+			sizeof(smode));
+	smode = FSI_MRESB_RST_GEN | FSI_MRESB_RST_ERR;
+	master->write(master, 0, 0, FSI_HUB_CONTROL + FSI_MRESB0, &smode,
+			sizeof(smode));
+
+	if (addr > FSI_HUB_LINK_OFFSET) {
+		smode = FSI_BREAK;
+		master->write(master, 0, 0, 0x100004, &smode, sizeof(smode));
+		smode = FSI_SLAVE_SMODE_DFLT;
+		master->write(master, 0, 0, 0x100800, &smode, sizeof(smode));
+	}
+
+	clear_bit(FSI_IN_ERR_CLEANUP, &fsi_state);
 }
 
 static int fsi_master_scan(struct fsi_master *master)
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH linux dev-4.7 v2 7/7] tools/testing/selftests: Add fsi command line tool
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
                   ` (5 preceding siblings ...)
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 6/7] drivers/fsi: Cleanup bus errors Christopher Bostic
@ 2017-02-21 21:50 ` Christopher Bostic
  2017-02-22  1:08 ` [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Jeremy Kerr
  2017-02-22 16:24 ` Andrew Geissler
  8 siblings, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-21 21:50 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Add command line tool to read/write CFAMs via the slave 'raw'
sysfs file.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
 tools/testing/selftests/fsi/fsitest.c | 163 ++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)
 create mode 100644 tools/testing/selftests/fsi/fsitest.c

diff --git a/tools/testing/selftests/fsi/fsitest.c b/tools/testing/selftests/fsi/fsitest.c
new file mode 100644
index 0000000..7aa3e7f
--- /dev/null
+++ b/tools/testing/selftests/fsi/fsitest.c
@@ -0,0 +1,163 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <string.h>
+
+int testread(int fd, uint32_t addr, uint32_t *value)
+{
+	int rc;
+
+	lseek(fd, addr, SEEK_SET);
+	rc = read(fd, value, 4);
+	if (rc >= 0)
+		rc = 0;
+
+	return rc;
+}
+
+int testwrite(int fd, uint32_t addr, uint32_t value)
+{
+	int rc;
+
+	lseek(fd, addr, SEEK_SET);
+	rc = write(fd, &value, 4);
+	if (rc >= 0)
+		rc = 0;
+
+	return rc;
+}
+
+#define NUM_WRITES	6
+#define NUM_READS	9
+#define NUM_HUB_READS	9
+
+int main(int argc, char **argv)
+{
+	int rc = 0;
+	int i, fd, option;
+	int skip_write = 0;
+	int verbose = 0;
+	int hub = 0;
+	char path[64] = "/sys/bus/platform/devices/fsi-master/slave@00:00/raw";
+	uint32_t value;
+	const uint32_t write_addresses[NUM_WRITES] = {
+		0x800,
+		0x818,
+		0x35D0,
+		0x100800,
+		0x100818,
+		0x1035D0,
+	};
+	const uint32_t addresses[NUM_READS] = {
+		0x800,	/* smode */
+		0x818,	/* si1m */
+		0x81C,	/* si1s */
+		0x101C,	/* scom status */
+		0x1028,	/* scom chipid */
+		0x1808,	/* i2c mode */
+		0x181C,	/* i2c status */
+		0x3400,	/* hub mmode */
+		0x35D0,	/* hub status */
+	};
+	const uint32_t hub_addresses[NUM_HUB_READS] = {
+		0x100800,	/* smode */
+		0x100818,	/* si1m */
+		0x10081C,	/* si1s */
+		0x10101C,	/* scom status */
+		0x101028,	/* scom chipid */
+		0x101808,	/* i2c mode */
+		0x10181C,	/* i2c status */
+		0x103400,	/* hub mmode */
+		0x1035D0,	/* hub status */
+	};
+
+	while ((option = getopt(argc, argv, "vsb:x")) != -1) {
+		switch (option) {
+		case 'v':
+			verbose = 1;
+			break;
+		case 's':
+			skip_write = 1;
+			break;
+		case 'b':
+			strncpy(path, optarg, 64);
+			break;
+		case 'x':
+			hub = 1;
+			break;
+		default:
+			printf("unknown option\n");
+		}
+	}
+
+	fd = open(path, O_RDWR);
+	if (fd < 0) {
+		printf("FAILED - failed to open %s\n", path);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < NUM_READS; ++i) {
+		rc = testread(fd, addresses[i], &value);
+		if (rc) {
+			printf("FAILED - failed to read %08x\n", addresses[i]);
+			goto exit;
+		}
+
+		if (verbose)
+			printf("read %08x: %08x\n", addresses[i], value);
+	}
+
+	if (!skip_write) {
+		for (i = 0; i < NUM_WRITES; ++i) {
+			value = 0;
+			rc = testread(fd, write_addresses[i], &value);
+			if (rc) {
+				printf("FAILED - failed to read %08x\n",
+				       write_addresses[i]);
+				goto exit;
+			}
+
+			rc = testwrite(fd, write_addresses[i], value);
+			if (rc) {
+				printf("FAILED - failed to write %08x\n",
+				       write_addresses[i]);
+				goto exit;
+			}
+
+			if (verbose)
+				printf("wrote %08x: %08x\n",
+				       write_addresses[i], value);
+		}
+	} else if (verbose)
+		printf("skipping write\n");
+
+	if (hub) {
+		for (i = 0; i < NUM_HUB_READS; ++i) {
+			rc = testread(fd, hub_addresses[i], &value);
+			if (rc) {
+				printf("FAILED - failed to read hub %08x\n",
+				       hub_addresses[i]);
+				goto exit;
+			}
+
+			if (verbose)
+				printf("read %08x: %08x\n", hub_addresses[i],
+				       value);
+		}
+	}
+
+	printf("SUCCESS\n");
+
+exit:
+	close(fd);
+
+	return rc;
+}
-- 
1.8.2.2

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect Christopher Bostic
@ 2017-02-22  1:00   ` Joel Stanley
  2017-02-22 16:34     ` Christopher Bostic
  2017-02-22 22:36     ` Christopher Bostic
  2017-02-22  1:13   ` Jeremy Kerr
  1 sibling, 2 replies; 23+ messages in thread
From: Joel Stanley @ 2017-02-22  1:00 UTC (permalink / raw)
  To: Christopher Bostic; +Cc: OpenBMC Maillist

On Wed, Feb 22, 2017 at 8:20 AM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> After each gpio master read/write check for bus errors.  If
> errors detected then clean it up and retry the original operation
> again.  If second attempt succeeds then don't report original
> error to caller.
>
> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
> ---
>  drivers/fsi/fsi-core.c        |  4 ++++
>  drivers/fsi/fsi-master-gpio.c | 24 ++++++++++++++++++++++--
>  drivers/fsi/fsi-master.h      |  3 +++
>  3 files changed, 29 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
> index 360c02a..428675f 100644
> --- a/drivers/fsi/fsi-core.c
> +++ b/drivers/fsi/fsi-core.c
> @@ -639,6 +639,10 @@ static int fsi_master_break(struct fsi_master *master, int link)
>         return 0;
>  }
>
> +void fsi_master_handle_error(struct fsi_master *master, uint32_t addr)
> +{
> +}
> +
>  static int fsi_master_scan(struct fsi_master *master)
>  {
>         int link, slave_id, rc;
> diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
> index 8aec538..5b502eb 100644
> --- a/drivers/fsi/fsi-master-gpio.c
> +++ b/drivers/fsi/fsi-master-gpio.c
> @@ -381,7 +381,17 @@ static int fsi_master_gpio_read(struct fsi_master *_master, int link,
>                 return -ENODEV;
>
>         build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
> -       return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
> +       rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
> +       if (rc) {
> +               fsi_master_handle_error(&master->master, addr);
> +
> +               /* Try again */
> +               rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
> +               if (rc)
> +                       fsi_master_handle_error(&master->master, addr);
> +       }
> +
> +       return rc;
>  }
>
>  static int fsi_master_gpio_write(struct fsi_master *_master, int link,
> @@ -395,7 +405,17 @@ static int fsi_master_gpio_write(struct fsi_master *_master, int link,
>                 return -ENODEV;
>
>         build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
> -       return send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
> +       rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
> +       if (rc) {
> +               fsi_master_handle_error(&master->master, addr);
> +
> +               /* Try again */

It's obvious from the code that we're trying again. You could change
the comment to indicate why we are trying again.

> +               rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
> +               if (rc)
> +                       fsi_master_handle_error(&master->master, addr);
> +       }

You're repeating yourself here. Perhaps a loop?

You have the same sequence in fsi_master_gpio_read. It would be nice
to not repeat the sequence.

> +
> +       return rc;
>  }
>
>  /*
> diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
> index 4a3176b..4ed416c 100644
> --- a/drivers/fsi/fsi-master.h
> +++ b/drivers/fsi/fsi-master.h
> @@ -19,6 +19,8 @@
>
>  #include <linux/device.h>
>
> +#include "fsi-master.h"

This looks wrong.

> +
>  /* Control Registers */
>  #define FSI_MMODE              0x0             /* R/W: mode */
>  #define FSI_MDLYR              0x4             /* R/W: delay */
> @@ -85,6 +87,7 @@ struct fsi_master {
>  extern int fsi_master_register(struct fsi_master *master);
>  extern void fsi_master_unregister(struct fsi_master *master);
>  extern int fsi_master_start_ipoll(struct fsi_master *master);
> +extern void fsi_master_handle_error(struct fsi_master *master, uint32_t addr);

Does this need to be added to the header?

>
>  /**
>   * crc4 helper: Given a starting crc4 state @c, calculate the crc4 vaue of @x,
> --
> 1.8.2.2
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 4/7] drivers/fsi: Move common read write ops into single function
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 4/7] drivers/fsi: Move common read write ops into single function Christopher Bostic
@ 2017-02-22  1:02   ` Joel Stanley
  0 siblings, 0 replies; 23+ messages in thread
From: Joel Stanley @ 2017-02-22  1:02 UTC (permalink / raw)
  To: Christopher Bostic; +Cc: OpenBMC Maillist

On Wed, Feb 22, 2017 at 8:20 AM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> Move common operations between gpio reads/writes into a new
> utility send_command.
>
> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
>
> ---
>
> v2: Separate the break out of common read/write elements into its
>     own separate patch.

Nice one.

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  drivers/fsi/fsi-master-gpio.c | 36 ++++++++++++++++++------------------
>  1 file changed, 18 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
> index 3ed82ea..8aec538 100644
> --- a/drivers/fsi/fsi-master-gpio.c
> +++ b/drivers/fsi/fsi-master-gpio.c
> @@ -354,26 +354,34 @@ static void build_abs_ar_command(struct fsi_gpio_msg *cmd, uint64_t mode,
>         cmd->msg >>= (64 - cmd->bits);
>  }
>
> +static int send_command(struct fsi_master_gpio *master,
> +                       struct fsi_gpio_msg *cmd, uint8_t expected,
> +                       size_t size, void *val)
> +{
> +       unsigned long flags;
> +       int rc;
> +
> +       spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
> +       serial_out(master, cmd);
> +       echo_delay(master);
> +       rc = poll_for_response(master, expected, size, val);
> +       spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
> +
> +       return rc;
> +}
> +
>  static int fsi_master_gpio_read(struct fsi_master *_master, int link,
>                 uint8_t slave, uint32_t addr, void *val, size_t size)
>  {
>         struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
>         struct fsi_gpio_msg cmd;
>         int rc;
> -       unsigned long flags;
>
>         if (link != 0)
>                 return -ENODEV;
>
>         build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
> -
> -       spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
> -       serial_out(master, &cmd);
> -       echo_delay(master);
> -       rc = poll_for_response(master, FSI_GPIO_RESP_ACKD, size, val);
> -       spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
> -
> -       return rc;
> +       return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>  }
>
>  static int fsi_master_gpio_write(struct fsi_master *_master, int link,
> @@ -382,20 +390,12 @@ static int fsi_master_gpio_write(struct fsi_master *_master, int link,
>         struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
>         struct fsi_gpio_msg cmd;
>         int rc;
> -       unsigned long flags;
>
>         if (link != 0)
>                 return -ENODEV;
>
>         build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
> -
> -       spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
> -       serial_out(master, &cmd);
> -       echo_delay(master);
> -       rc = poll_for_response(master, FSI_GPIO_RESP_ACK, size, NULL);
> -       spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
> -
> -       return rc;
> +       return send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
>  }
>
>  /*
> --
> 1.8.2.2
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect Christopher Bostic
@ 2017-02-22  1:02   ` Jeremy Kerr
  2017-02-22 15:29     ` Christopher Bostic
  0 siblings, 1 reply; 23+ messages in thread
From: Jeremy Kerr @ 2017-02-22  1:02 UTC (permalink / raw)
  To: Christopher Bostic, joel; +Cc: openbmc

Hi Chris,

> @@ -252,7 +271,31 @@ static int fsi_slave_scan(struct fsi_slave *slave)
>  		 * Unused address areas are marked by a zero type value; this
>  		 * skips the defined address areas
>  		 */
> -		if (type != 0 && slots != 0) {
> +		if (type != 0) {
> +
> +			if (type == FSI_ENGID_HUB_MASTER) {

I'd split this into a separate part of the above 'if' statement. Or,
convert it to a switch.

> +				hub = kzalloc(sizeof(*hub), GFP_KERNEL);
> +				if (!hub)
> +					return -ENOMEM;
> +
> +				hub->base = FSI_HUB_LINK_OFFSET;
> +				hub->control_regs = engine_addr;
> +				hub->slave = slave;
> +				rc = hub_master_init(hub);
> +
> +				continue;
> +			}
> +			if (type == FSI_ENGID_HUB_LINK) {
> +				if (!hub)
> +					continue;
> +
> +				hub->master.n_links++;
> +				if (hub->master.n_links ==
> +						(FSI_HUB_MASTER_MAX_LINKS * 2))
> +					rc = fsi_master_register(&hub->master);
> +
> +				continue;
> +			}

This logic doesn't make a lot of sense. You're counting the number of
link slots, but then registering the master when that count hits a
predefined number. I'd suggest either:

 - just setting n_links to the predefined number; or

 - keeping a separate variable for n_links, and then once we've finished
   scanning the configuration table (after the for loop)

    if (hub) {
	    hub->n_links = conf_link_count / 2;
	    fsi_master_register(&hub->master);
    }

I'd much prefer the second option, as that actually uses the link count
from the config table.

>  int fsi_master_register(struct fsi_master *master)
>  {
> -	if (!master || !master->dev)
> +	if (!master)
>  		return -EINVAL;

I'm worried if this is needed - we should be creating a device for all
masters.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 3/7] drivers/fsi: Define hub master callbacks
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 3/7] drivers/fsi: Define hub master callbacks Christopher Bostic
@ 2017-02-22  1:06   ` Jeremy Kerr
  2017-02-22 16:33     ` Christopher Bostic
  0 siblings, 1 reply; 23+ messages in thread
From: Jeremy Kerr @ 2017-02-22  1:06 UTC (permalink / raw)
  To: Christopher Bostic, joel; +Cc: openbmc

Hi Chris,

> Define hub master read, write, link enable, and break ops.

Now that we have things more contained, you may want to add the complete
hub functionality in one patch.

However:

> @@ -571,6 +598,7 @@ static int fsi_slave_init(struct fsi_master *master,
>  	slave->id = slave_id;
>  	slave->dev.parent = master->dev;
>  	slave->dev.release = fsi_slave_release;
> +	slave->link = link;
>  
>  	dev_set_name(&slave->dev, "slave@%02x:%02x", link, slave_id);
>  	rc = device_register(&slave->dev);

This looks like a generally-useful fix, for more than just the hub code.

Otherwise, looks good.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
                   ` (6 preceding siblings ...)
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 7/7] tools/testing/selftests: Add fsi command line tool Christopher Bostic
@ 2017-02-22  1:08 ` Jeremy Kerr
  2017-02-22 15:27   ` Christopher Bostic
  2017-02-22 16:24 ` Andrew Geissler
  8 siblings, 1 reply; 23+ messages in thread
From: Jeremy Kerr @ 2017-02-22  1:08 UTC (permalink / raw)
  To: Christopher Bostic, joel; +Cc: openbmc

Hi Chris,

> Adds the FSI hub master functionality to the OpenFSI device driver.
> Hub master is a FSI client device driver that registers with the
> core and is notified when devices it wants, hub master engine and
> links, are discovered.
> 
> v2: Restructured to move hub into the core instead of a separate
>     slave device driver.
> 
> Christopher Bostic (7):
>   drivers/fsi: Add hub master scan detect
>   drivers/fsi: Initialize hub master
>   drivers/fsi: Define hub master callbacks
>   drivers/fsi: Move common read write ops into single function
>   drivers/fsi: Add retry on bus error detect
>   drivers/fsi: Cleanup bus errors
>   tools/testing/selftests: Add fsi command line tool

This changeset seems to add both the hub master, and the generic error
handing. Could this be split into two series?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect Christopher Bostic
  2017-02-22  1:00   ` Joel Stanley
@ 2017-02-22  1:13   ` Jeremy Kerr
  2017-02-22 16:37     ` Christopher Bostic
  1 sibling, 1 reply; 23+ messages in thread
From: Jeremy Kerr @ 2017-02-22  1:13 UTC (permalink / raw)
  To: Christopher Bostic, joel; +Cc: openbmc

Hi Chris,

> --- a/drivers/fsi/fsi-master-gpio.c
> +++ b/drivers/fsi/fsi-master-gpio.c
> @@ -381,7 +381,17 @@ static int fsi_master_gpio_read(struct fsi_master *_master, int link,
>  		return -ENODEV;
>  
>  	build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
> -	return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
> +	rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
> +	if (rc) {
> +		fsi_master_handle_error(&master->master, addr);
> +
> +		/* Try again */
> +		rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
> +		if (rc)
> +			fsi_master_handle_error(&master->master, addr);
> +	}
> +
> +	return rc;

Lets avoid the repeated code:

	const static int master_retries = 2;

	[...]

	for (retries = 0; retries < master_retries; retries++) {
		rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
		if (!rc)
			break;
		fsi_master_handle_error(&master->master, addr);
	}

	return rc;

[or even better, we may want to put this in a helper, for use by both
call sites]

Also, is there any condition where fsi_master_handle_error() knows that
the FSI bus is totally hosed, and there's no point retrying?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master
  2017-02-22  1:08 ` [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Jeremy Kerr
@ 2017-02-22 15:27   ` Christopher Bostic
  0 siblings, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-22 15:27 UTC (permalink / raw)
  To: Jeremy Kerr, joel; +Cc: openbmc



On 2/21/17 7:08 PM, Jeremy Kerr wrote:
> Hi Chris,
>
>> Adds the FSI hub master functionality to the OpenFSI device driver.
>> Hub master is a FSI client device driver that registers with the
>> core and is notified when devices it wants, hub master engine and
>> links, are discovered.
>>
>> v2: Restructured to move hub into the core instead of a separate
>>      slave device driver.
>>
>> Christopher Bostic (7):
>>    drivers/fsi: Add hub master scan detect
>>    drivers/fsi: Initialize hub master
>>    drivers/fsi: Define hub master callbacks
>>    drivers/fsi: Move common read write ops into single function
>>    drivers/fsi: Add retry on bus error detect
>>    drivers/fsi: Cleanup bus errors
>>    tools/testing/selftests: Add fsi command line tool
> This changeset seems to add both the hub master, and the generic error
> handing. Could this be split into two series?
Hi Jeremy,

Sure, will split those up.

Thanks


> Cheers,
>
>
> Jeremy
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect
  2017-02-22  1:02   ` Jeremy Kerr
@ 2017-02-22 15:29     ` Christopher Bostic
  0 siblings, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-22 15:29 UTC (permalink / raw)
  To: Jeremy Kerr, joel; +Cc: openbmc



On 2/21/17 7:02 PM, Jeremy Kerr wrote:
> Hi Chris,
>
>> @@ -252,7 +271,31 @@ static int fsi_slave_scan(struct fsi_slave *slave)
>>   		 * Unused address areas are marked by a zero type value; this
>>   		 * skips the defined address areas
>>   		 */
>> -		if (type != 0 && slots != 0) {
>> +		if (type != 0) {
>> +
>> +			if (type == FSI_ENGID_HUB_MASTER) {
> I'd split this into a separate part of the above 'if' statement. Or,
> convert it to a switch.

Hi Jeremy,

Will change.

>> +				hub = kzalloc(sizeof(*hub), GFP_KERNEL);
>> +				if (!hub)
>> +					return -ENOMEM;
>> +
>> +				hub->base = FSI_HUB_LINK_OFFSET;
>> +				hub->control_regs = engine_addr;
>> +				hub->slave = slave;
>> +				rc = hub_master_init(hub);
>> +
>> +				continue;
>> +			}
>> +			if (type == FSI_ENGID_HUB_LINK) {
>> +				if (!hub)
>> +					continue;
>> +
>> +				hub->master.n_links++;
>> +				if (hub->master.n_links ==
>> +						(FSI_HUB_MASTER_MAX_LINKS * 2))
>> +					rc = fsi_master_register(&hub->master);
>> +
>> +				continue;
>> +			}
> This logic doesn't make a lot of sense. You're counting the number of
> link slots, but then registering the master when that count hits a
> predefined number. I'd suggest either:
>
>   - just setting n_links to the predefined number; or
>
>   - keeping a separate variable for n_links, and then once we've finished
>     scanning the configuration table (after the for loop)
>
>      if (hub) {
> 	    hub->n_links = conf_link_count / 2;
> 	    fsi_master_register(&hub->master);
>      }
>
> I'd much prefer the second option, as that actually uses the link count
> from the config table.

Will implement the second option

>>   int fsi_master_register(struct fsi_master *master)
>>   {
>> -	if (!master || !master->dev)
>> +	if (!master)
>>   		return -EINVAL;
> I'm worried if this is needed - we should be creating a device for all
> masters.

Will add a dev for struct fsi_master.

Thanks

> Cheers,
>
>
> Jeremy
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master
  2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
                   ` (7 preceding siblings ...)
  2017-02-22  1:08 ` [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Jeremy Kerr
@ 2017-02-22 16:24 ` Andrew Geissler
  8 siblings, 0 replies; 23+ messages in thread
From: Andrew Geissler @ 2017-02-22 16:24 UTC (permalink / raw)
  To: Christopher Bostic; +Cc: Joel Stanley, OpenBMC Maillist

On Tue, Feb 21, 2017 at 3:50 PM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> Adds the FSI hub master functionality to the OpenFSI device driver.
> Hub master is a FSI client device driver that registers with the
> core and is notified when devices it wants, hub master engine and
> links, are discovered.
>
> v2: Restructured to move hub into the core instead of a separate
>     slave device driver.
>
> Christopher Bostic (7):
>   drivers/fsi: Add hub master scan detect
>   drivers/fsi: Initialize hub master
>   drivers/fsi: Define hub master callbacks
>   drivers/fsi: Move common read write ops into single function
>   drivers/fsi: Add retry on bus error detect
>   drivers/fsi: Cleanup bus errors
>   tools/testing/selftests: Add fsi command line tool
>
>
> --
> 1.8.2.2
>

Do I need to respond that I tested to all commits in this series?
I'll just do this one for now.

I built all patches into an image and we verified all is looking good
on Witherspoon and Zaius.

Tested-by: Andrew Geissler <geissonator@gmail.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 3/7] drivers/fsi: Define hub master callbacks
  2017-02-22  1:06   ` Jeremy Kerr
@ 2017-02-22 16:33     ` Christopher Bostic
  0 siblings, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-22 16:33 UTC (permalink / raw)
  To: Jeremy Kerr, joel; +Cc: openbmc



On 2/21/17 7:06 PM, Jeremy Kerr wrote:
> Hi Chris,
>
>> Define hub master read, write, link enable, and break ops.
> Now that we have things more contained, you may want to add the complete
> hub functionality in one patch.
Hi Jeremy,

OK will add all in one patch.

> However:
>
>> @@ -571,6 +598,7 @@ static int fsi_slave_init(struct fsi_master *master,
>>   	slave->id = slave_id;
>>   	slave->dev.parent = master->dev;
>>   	slave->dev.release = fsi_slave_release;
>> +	slave->link = link;
>>   
>>   	dev_set_name(&slave->dev, "slave@%02x:%02x", link, slave_id);
>>   	rc = device_register(&slave->dev);
> This looks like a generally-useful fix, for more than just the hub code.

This was uncovered in hub link testing.  Will treat it as a separate
patch from hub  and error handling.

Thanks


> Otherwise, looks good.
>
> Cheers,
>
>
> Jeremy
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect
  2017-02-22  1:00   ` Joel Stanley
@ 2017-02-22 16:34     ` Christopher Bostic
  2017-02-22 22:36     ` Christopher Bostic
  1 sibling, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-22 16:34 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist



On 2/21/17 7:00 PM, Joel Stanley wrote:
> On Wed, Feb 22, 2017 at 8:20 AM, Christopher Bostic
> <cbostic@linux.vnet.ibm.com> wrote:
>> After each gpio master read/write check for bus errors.  If
>> errors detected then clean it up and retry the original operation
>> again.  If second attempt succeeds then don't report original
>> error to caller.
>>
>> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
>> ---
>>   drivers/fsi/fsi-core.c        |  4 ++++
>>   drivers/fsi/fsi-master-gpio.c | 24 ++++++++++++++++++++++--
>>   drivers/fsi/fsi-master.h      |  3 +++
>>   3 files changed, 29 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
>> index 360c02a..428675f 100644
>> --- a/drivers/fsi/fsi-core.c
>> +++ b/drivers/fsi/fsi-core.c
>> @@ -639,6 +639,10 @@ static int fsi_master_break(struct fsi_master *master, int link)
>>          return 0;
>>   }
>>
>> +void fsi_master_handle_error(struct fsi_master *master, uint32_t addr)
>> +{
>> +}
>> +
>>   static int fsi_master_scan(struct fsi_master *master)
>>   {
>>          int link, slave_id, rc;
>> diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
>> index 8aec538..5b502eb 100644
>> --- a/drivers/fsi/fsi-master-gpio.c
>> +++ b/drivers/fsi/fsi-master-gpio.c
>> @@ -381,7 +381,17 @@ static int fsi_master_gpio_read(struct fsi_master *_master, int link,
>>                  return -ENODEV;
>>
>>          build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
>> -       return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +       rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +       if (rc) {
>> +               fsi_master_handle_error(&master->master, addr);
>> +
>> +               /* Try again */
>> +               rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +               if (rc)
>> +                       fsi_master_handle_error(&master->master, addr);
>> +       }
>> +
>> +       return rc;
>>   }
>>
>>   static int fsi_master_gpio_write(struct fsi_master *_master, int link,
>> @@ -395,7 +405,17 @@ static int fsi_master_gpio_write(struct fsi_master *_master, int link,
>>                  return -ENODEV;
>>
>>          build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
>> -       return send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
>> +       rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
>> +       if (rc) {
>> +               fsi_master_handle_error(&master->master, addr);
>> +
>> +               /* Try again */
> It's obvious from the code that we're trying again. You could change
> the comment to indicate why we are trying again.

Hi Joel

will update.
>> +               rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
>> +               if (rc)
>> +                       fsi_master_handle_error(&master->master, addr);
>> +       }
> You're repeating yourself here. Perhaps a loop?
>
> You have the same sequence in fsi_master_gpio_read. It would be nice
> to not repeat the sequence.

OK, will add a loop here.

>> +
>> +       return rc;
>>   }
>>
>>   /*
>> diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
>> index 4a3176b..4ed416c 100644
>> --- a/drivers/fsi/fsi-master.h
>> +++ b/drivers/fsi/fsi-master.h
>> @@ -19,6 +19,8 @@
>>
>>   #include <linux/device.h>
>>
>> +#include "fsi-master.h"
> This looks wrong.
>
>> +
>>   /* Control Registers */
>>   #define FSI_MMODE              0x0             /* R/W: mode */
>>   #define FSI_MDLYR              0x4             /* R/W: delay */
>> @@ -85,6 +87,7 @@ struct fsi_master {
>>   extern int fsi_master_register(struct fsi_master *master);
>>   extern void fsi_master_unregister(struct fsi_master *master);
>>   extern int fsi_master_start_ipoll(struct fsi_master *master);
>> +extern void fsi_master_handle_error(struct fsi_master *master, uint32_t addr);
> Does this need to be added to the header?

Probably not, will remove.

Thanks,
Chris

>>   /**
>>    * crc4 helper: Given a starting crc4 state @c, calculate the crc4 vaue of @x,
>> --
>> 1.8.2.2
>>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect
  2017-02-22  1:13   ` Jeremy Kerr
@ 2017-02-22 16:37     ` Christopher Bostic
  0 siblings, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-22 16:37 UTC (permalink / raw)
  To: Jeremy Kerr, joel; +Cc: openbmc



On 2/21/17 7:13 PM, Jeremy Kerr wrote:
> Hi Chris,
>
>> --- a/drivers/fsi/fsi-master-gpio.c
>> +++ b/drivers/fsi/fsi-master-gpio.c
>> @@ -381,7 +381,17 @@ static int fsi_master_gpio_read(struct fsi_master *_master, int link,
>>   		return -ENODEV;
>>   
>>   	build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
>> -	return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +	rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +	if (rc) {
>> +		fsi_master_handle_error(&master->master, addr);
>> +
>> +		/* Try again */
>> +		rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +		if (rc)
>> +			fsi_master_handle_error(&master->master, addr);
>> +	}
>> +
>> +	return rc;
> Lets avoid the repeated code:
>
> 	const static int master_retries = 2;
>
> 	[...]
>
> 	for (retries = 0; retries < master_retries; retries++) {
> 		rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
> 		if (!rc)
> 			break;
> 		fsi_master_handle_error(&master->master, addr);
> 	}
>
> 	return rc;
>
> [or even better, we may want to put this in a helper, for use by both
> call sites]
Hi Jeremy,

Will change to a loop.


> Also, is there any condition where fsi_master_handle_error() knows that
> the FSI bus is totally hosed, and there's no point retrying?

There's not anything defined to flag a bad bus -will look into it.

Thanks,
Chris

> Cheers,
>
>
> Jeremy
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 6/7] drivers/fsi: Cleanup bus errors
  2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 6/7] drivers/fsi: Cleanup bus errors Christopher Bostic
@ 2017-02-22 21:55   ` Jeremy Kerr
  2017-02-22 22:51     ` Christopher Bostic
  0 siblings, 1 reply; 23+ messages in thread
From: Jeremy Kerr @ 2017-02-22 21:55 UTC (permalink / raw)
  To: Christopher Bostic, joel; +Cc: openbmc

Hi Chris,

> @@ -255,6 +263,10 @@ int hub_master_break(struct fsi_master *master, int linkno)
>  	uint32_t break_offset = 0x4; /* hw workaround */
>  	uint32_t addr;
>  
> +	/* config table lists 2 entries per hub link */
> +	if (linkno >= (master->n_links / 2))
> +		return -ENODEV;
> +

master->n_links should represent the actual number of links, rather than
reflect what's in the config table.

[besides, don't we do the / 2 during the config table parse anyway?]

>  	command = FSI_BREAK;
>  	addr = (linkno * FSI_MASTER_HUB_LINK_SIZE) + hub->base;
>  	return fsi_slave_write(hub->slave, addr + break_offset, &command,
> @@ -641,6 +653,28 @@ static int fsi_master_break(struct fsi_master *master, int link)
>  
>  void fsi_master_handle_error(struct fsi_master *master, uint32_t addr)
>  {
> +	uint32_t smode = FSI_SLAVE_SMODE_DFLT;
> +
> +	/* Avoid nested error handling */
> +	if (test_and_set_bit(FSI_IN_ERR_CLEANUP, &fsi_state))
> +		return;

Do we have any other bits of state to represent? If not, just use a
plain atomic_t rather than a set of flags.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect
  2017-02-22  1:00   ` Joel Stanley
  2017-02-22 16:34     ` Christopher Bostic
@ 2017-02-22 22:36     ` Christopher Bostic
  1 sibling, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-22 22:36 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist



On 2/21/17 7:00 PM, Joel Stanley wrote:
> On Wed, Feb 22, 2017 at 8:20 AM, Christopher Bostic
> <cbostic@linux.vnet.ibm.com> wrote:
>> After each gpio master read/write check for bus errors.  If
>> errors detected then clean it up and retry the original operation
>> again.  If second attempt succeeds then don't report original
>> error to caller.
>>
>> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
>> ---
>>   drivers/fsi/fsi-core.c        |  4 ++++
>>   drivers/fsi/fsi-master-gpio.c | 24 ++++++++++++++++++++++--
>>   drivers/fsi/fsi-master.h      |  3 +++
>>   3 files changed, 29 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
>> index 360c02a..428675f 100644
>> --- a/drivers/fsi/fsi-core.c
>> +++ b/drivers/fsi/fsi-core.c
>> @@ -639,6 +639,10 @@ static int fsi_master_break(struct fsi_master *master, int link)
>>          return 0;
>>   }
>>
>> +void fsi_master_handle_error(struct fsi_master *master, uint32_t addr)
>> +{
>> +}
>> +
>>   static int fsi_master_scan(struct fsi_master *master)
>>   {
>>          int link, slave_id, rc;
>> diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
>> index 8aec538..5b502eb 100644
>> --- a/drivers/fsi/fsi-master-gpio.c
>> +++ b/drivers/fsi/fsi-master-gpio.c
>> @@ -381,7 +381,17 @@ static int fsi_master_gpio_read(struct fsi_master *_master, int link,
>>                  return -ENODEV;
>>
>>          build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
>> -       return send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +       rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +       if (rc) {
>> +               fsi_master_handle_error(&master->master, addr);
>> +
>> +               /* Try again */
>> +               rc = send_command(master, &cmd, FSI_GPIO_RESP_ACKD, size, val);
>> +               if (rc)
>> +                       fsi_master_handle_error(&master->master, addr);
>> +       }
>> +
>> +       return rc;
>>   }
>>
>>   static int fsi_master_gpio_write(struct fsi_master *_master, int link,
>> @@ -395,7 +405,17 @@ static int fsi_master_gpio_write(struct fsi_master *_master, int link,
>>                  return -ENODEV;
>>
>>          build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
>> -       return send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
>> +       rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
>> +       if (rc) {
>> +               fsi_master_handle_error(&master->master, addr);
>> +
>> +               /* Try again */
> It's obvious from the code that we're trying again. You could change
> the comment to indicate why we are trying again.
>
>> +               rc = send_command(master, &cmd, FSI_GPIO_RESP_ACK, size, NULL);
>> +               if (rc)
>> +                       fsi_master_handle_error(&master->master, addr);
>> +       }
> You're repeating yourself here. Perhaps a loop?
>
> You have the same sequence in fsi_master_gpio_read. It would be nice
> to not repeat the sequence.
>
>> +
>> +       return rc;
>>   }
>>
>>   /*
>> diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
>> index 4a3176b..4ed416c 100644
>> --- a/drivers/fsi/fsi-master.h
>> +++ b/drivers/fsi/fsi-master.h
>> @@ -19,6 +19,8 @@
>>
>>   #include <linux/device.h>
>>
>> +#include "fsi-master.h"
> This looks wrong.
>
>> +
>>   /* Control Registers */
>>   #define FSI_MMODE              0x0             /* R/W: mode */
>>   #define FSI_MDLYR              0x4             /* R/W: delay */
>> @@ -85,6 +87,7 @@ struct fsi_master {
>>   extern int fsi_master_register(struct fsi_master *master);
>>   extern void fsi_master_unregister(struct fsi_master *master);
>>   extern int fsi_master_start_ipoll(struct fsi_master *master);
>> +extern void fsi_master_handle_error(struct fsi_master *master, uint32_t addr);
> Does this need to be added to the header?

Hi Joel,

Yes, since the gpio master is requiring a core function,  similar to 
fsi_master_register()/unregister()

Thanks,
Chris
>>   /**
>>    * crc4 helper: Given a starting crc4 state @c, calculate the crc4 vaue of @x,
>> --
>> 1.8.2.2
>>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH linux dev-4.7 v2 6/7] drivers/fsi: Cleanup bus errors
  2017-02-22 21:55   ` Jeremy Kerr
@ 2017-02-22 22:51     ` Christopher Bostic
  0 siblings, 0 replies; 23+ messages in thread
From: Christopher Bostic @ 2017-02-22 22:51 UTC (permalink / raw)
  To: Jeremy Kerr, joel; +Cc: openbmc



On 2/22/17 3:55 PM, Jeremy Kerr wrote:
> Hi Chris,
>
>> @@ -255,6 +263,10 @@ int hub_master_break(struct fsi_master *master, int linkno)
>>   	uint32_t break_offset = 0x4; /* hw workaround */
>>   	uint32_t addr;
>>   
>> +	/* config table lists 2 entries per hub link */
>> +	if (linkno >= (master->n_links / 2))
>> +		return -ENODEV;
>> +
> master->n_links should represent the actual number of links, rather than
> reflect what's in the config table.
>
> [besides, don't we do the / 2 during the config table parse anyway?]

Hi Jeremy,

Yes that's true, its set in scan so no need for the /2 here - will fix.


>>   	command = FSI_BREAK;
>>   	addr = (linkno * FSI_MASTER_HUB_LINK_SIZE) + hub->base;
>>   	return fsi_slave_write(hub->slave, addr + break_offset, &command,
>> @@ -641,6 +653,28 @@ static int fsi_master_break(struct fsi_master *master, int link)
>>   
>>   void fsi_master_handle_error(struct fsi_master *master, uint32_t addr)
>>   {
>> +	uint32_t smode = FSI_SLAVE_SMODE_DFLT;
>> +
>> +	/* Avoid nested error handling */
>> +	if (test_and_set_bit(FSI_IN_ERR_CLEANUP, &fsi_state))
>> +		return;
> Do we have any other bits of state to represent? If not, just use a
> plain atomic_t rather than a set of flags.
No others at this point,  will change to an atomic_t

Thanks,
Chris

> Cheers,
>
>
> Jeremy
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2017-02-22 22:51 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-21 21:50 [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Christopher Bostic
2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 1/7] drivers/fsi: Add hub master scan detect Christopher Bostic
2017-02-22  1:02   ` Jeremy Kerr
2017-02-22 15:29     ` Christopher Bostic
2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 2/7] drivers/fsi: Initialize hub master Christopher Bostic
2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 3/7] drivers/fsi: Define hub master callbacks Christopher Bostic
2017-02-22  1:06   ` Jeremy Kerr
2017-02-22 16:33     ` Christopher Bostic
2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 4/7] drivers/fsi: Move common read write ops into single function Christopher Bostic
2017-02-22  1:02   ` Joel Stanley
2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 5/7] drivers/fsi: Add retry on bus error detect Christopher Bostic
2017-02-22  1:00   ` Joel Stanley
2017-02-22 16:34     ` Christopher Bostic
2017-02-22 22:36     ` Christopher Bostic
2017-02-22  1:13   ` Jeremy Kerr
2017-02-22 16:37     ` Christopher Bostic
2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 6/7] drivers/fsi: Cleanup bus errors Christopher Bostic
2017-02-22 21:55   ` Jeremy Kerr
2017-02-22 22:51     ` Christopher Bostic
2017-02-21 21:50 ` [PATCH linux dev-4.7 v2 7/7] tools/testing/selftests: Add fsi command line tool Christopher Bostic
2017-02-22  1:08 ` [PATCH linux dev-4.7 v2 0/7] drivers/fsi: Add hub master Jeremy Kerr
2017-02-22 15:27   ` Christopher Bostic
2017-02-22 16:24 ` Andrew Geissler

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.