All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel
@ 2017-05-09 21:38 Christopher Bostic
  2017-05-09 21:38 ` [PATCH linux dev-4.10 1/7] drivers/fsi: Add slave interrupt polling Christopher Bostic
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:38 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

These changes bring the 4.10 kernel FSI device driver up to date
with the 4.7 kernel version.

* Add basic and hub interrupt support
* Bug fixes introduced during 4.7 to 4.10 migration
* FSI protocol modification for added operational stability

Christopher Bostic (5):
  drivers/fsi: Add slave interrupt polling
  drivers/fsi: Scan for hub sourced IRQ's
  drivers/fsi: Set IRQ masks along hub path
  drivers/fsi: Unscan on master unregister
  drivers/fsi: GPIO stability changes for Cronus/Hostboot

Eddie James (2):
  drivers/fsi: Add Client IRQ Enable / Disable
  drivers/fsi: Fix one and two byte bus reads/writes


-- 
1.8.2.2

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

* [PATCH linux dev-4.10 1/7] drivers/fsi: Add slave interrupt polling
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
@ 2017-05-09 21:38 ` Christopher Bostic
  2017-05-10 22:26   ` Eddie James
  2017-05-09 21:38 ` [PATCH linux dev-4.10 2/7] drivers/fsi: Add Client IRQ Enable / Disable Christopher Bostic
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:38 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc, Eddie James

Scan slaves present for asserting interrupt signals in the
si1s register and call a registered client's interrupt handler as
appropriate.

Includes initial code from Eddie James <eajames@us.ibm.com>

Signed-off-by: Eddie James <eajames@us.ibm.com>
Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c   | 110 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/fsi/fsi-master.h |   1 +
 include/linux/fsi.h      |   5 +++
 3 files changed, 116 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index a6ed34f..73fdb69 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -15,9 +15,11 @@
 
 #include <linux/device.h>
 #include <linux/fsi.h>
+#include <linux/kthread.h>
 #include <linux/idr.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 
 #include "fsi-master.h"
 
@@ -38,8 +40,11 @@
 #define FSI_PEEK_BASE			0x410
 
 static const int engine_page_size = 0x400;
+static struct task_struct *master_ipoll;
+static unsigned int fsi_ipoll_period_ms = 100;
 
 #define FSI_SLAVE_BASE			0x800
+#define FSI_IPOLL_PERIOD		msecs_to_jiffies(fsi_ipoll_period_ms)
 
 /*
  * FSI slave engine control register offsets
@@ -47,6 +52,8 @@
 #define FSI_SMODE		0x0	/* R/W: Mode register */
 #define FSI_SISC		0x8	/* R/W: Interrupt condition */
 #define FSI_SSTAT		0x14	/* R  : Slave status */
+#define FSI_SI1M		0x18	/* R/W: IRQ mask */
+#define FSI_SI1S		0x1C	/* R  : IRQ status */
 #define FSI_LLMODE		0x100	/* R/W: Link layer mode register */
 
 /*
@@ -342,6 +349,7 @@ static int fsi_slave_scan(struct fsi_slave *slave)
 	uint32_t engine_addr;
 	uint32_t conf;
 	int rc, i;
+	uint8_t si1s_bit = 1;
 
 	/*
 	 * scan engines
@@ -396,6 +404,7 @@ static int fsi_slave_scan(struct fsi_slave *slave)
 			dev->unit = i;
 			dev->addr = engine_addr;
 			dev->size = slots * engine_page_size;
+			dev->si1s_bit = si1s_bit++;
 
 			dev_info(&slave->dev,
 			"engine[%i]: type %x, version %x, addr %x size %x\n",
@@ -761,6 +770,90 @@ static void fsi_master_unscan(struct fsi_master *master)
 	device_for_each_child(&master->dev, NULL, __fsi_master_remove_slave);
 }
 
+static int __fsi_dev_irq(struct device *dev, void *data)
+{
+	uint32_t *si1s = data;
+	struct fsi_device *fsi_dev = to_fsi_dev(dev);
+
+	if (!fsi_dev || !si1s) {
+		dev_dbg(dev, "Invalid input: %p %p\n", fsi_dev, si1s);
+		return -EINVAL;
+	}
+
+	if (*si1s & (0x80000000 >> fsi_dev->si1s_bit) &&
+					fsi_dev->irq_handler) {
+		fsi_dev->irq_handler(0, &fsi_dev->dev);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int __fsi_slave_irq(struct device *dev, void *data)
+{
+	return device_for_each_child(dev, data, __fsi_dev_irq);
+}
+
+static void fsi_master_irq(struct fsi_master *master, int link, uint32_t si1s)
+{
+	device_for_each_child(&master->dev, &si1s, __fsi_slave_irq);
+}
+
+static int fsi_master_ipoll(void *data)
+{
+	int rc;
+	uint32_t si1s;
+	unsigned long elapsed = 0;
+	unsigned long previous_jiffies = jiffies;
+	struct fsi_master *master = data;
+
+	while (!kthread_should_stop()) {
+		if (!master->ipoll)
+			goto done;
+
+		/* Ignore errors for now */
+		rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1S,
+				&si1s, sizeof(uint32_t));
+		if (rc)
+			goto done;
+
+		if (si1s & master->ipoll)
+			fsi_master_irq(master, 0, si1s);
+done:
+		elapsed = jiffies = previous_jiffies;
+		if (elapsed < FSI_IPOLL_PERIOD) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(FSI_IPOLL_PERIOD - elapsed);
+		}
+		previous_jiffies = jiffies;
+	}
+
+	return 0;
+}
+
+/*
+ * TODO: move this to master->start_ipoll() - each master may have its
+ * own way of doing this
+ */
+int fsi_master_start_ipoll(struct fsi_master *master)
+{
+	if (master_ipoll) {
+		dev_err(&master->dev, "Already polling for irqs\n");
+		return -EALREADY;
+	}
+	master_ipoll = kthread_create(fsi_master_ipoll, master,
+					"fsi_master_ipoll");
+	if (IS_ERR(master_ipoll)) {
+		dev_err(&master->dev, "Coudn't create ipoll thread rc:%d\n",
+			(int)PTR_ERR(master_ipoll));
+		return PTR_ERR(master_ipoll);
+	}
+	wake_up_process(master_ipoll);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fsi_master_start_ipoll);
+
 static ssize_t master_rescan_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
@@ -768,6 +861,7 @@ static ssize_t master_rescan_store(struct device *dev,
 
 	fsi_master_unscan(master);
 	fsi_master_scan(master);
+	fsi_master_start_ipoll(master);
 
 	return count;
 }
@@ -829,6 +923,11 @@ void fsi_master_unregister(struct fsi_master *master)
 		master->idx = -1;
 	}
 
+	if (master_ipoll) {
+		kthread_stop(master_ipoll);
+		master_ipoll = NULL;
+	}
+
 	device_unregister(&master->dev);
 }
 EXPORT_SYMBOL_GPL(fsi_master_unregister);
@@ -872,6 +971,17 @@ void fsi_driver_unregister(struct fsi_driver *fsi_drv)
 }
 EXPORT_SYMBOL_GPL(fsi_driver_unregister);
 
+int fsi_enable_irq(struct fsi_device *dev)
+{
+	return 0;
+}
+EXPORT_SYMBOL(fsi_enable_irq);
+
+void fsi_disable_irq(struct fsi_device *dev)
+{
+}
+EXPORT_SYMBOL(fsi_disable_irq);
+
 struct bus_type fsi_bus_type = {
 	.name		= "fsi",
 	.match		= fsi_bus_match,
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index fd39924..668ab0c 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -26,6 +26,7 @@ struct fsi_master {
 	int		idx;
 	int		n_links;
 	int		flags;
+	uint32_t	ipoll;
 	int		(*read)(struct fsi_master *, int link, uint8_t id,
 				uint32_t addr, void *val, size_t size);
 	int		(*write)(struct fsi_master *, int link, uint8_t id,
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 141fd38..bb5c6c6 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -22,9 +22,11 @@ struct fsi_device {
 	u8			engine_type;
 	u8			version;
 	u8			unit;
+	u8			si1s_bit;
 	struct fsi_slave	*slave;
 	uint32_t		addr;
 	uint32_t		size;
+	int (*irq_handler)(int, void *);
 };
 
 extern int fsi_device_read(struct fsi_device *dev, uint32_t addr,
@@ -80,4 +82,7 @@ extern int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 
 extern struct bus_type fsi_bus_type;
 
+extern int fsi_enable_irq(struct fsi_device *dev);
+extern void fsi_disable_irq(struct fsi_device *dev);
+
 #endif /* LINUX_FSI_H */
-- 
1.8.2.2

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

* [PATCH linux dev-4.10 2/7] drivers/fsi: Add Client IRQ Enable / Disable
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
  2017-05-09 21:38 ` [PATCH linux dev-4.10 1/7] drivers/fsi: Add slave interrupt polling Christopher Bostic
@ 2017-05-09 21:38 ` Christopher Bostic
  2017-05-09 21:38 ` [PATCH linux dev-4.10 3/7] drivers/fsi: Scan for hub sourced IRQ's Christopher Bostic
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:38 UTC (permalink / raw)
  To: joel; +Cc: Eddie James, openbmc, Christopher Bostic

From: Eddie James <eajames@us.ibm.com>

Allow FSI client drivers to enable and disable their engine
IRQ's via the exported interfaces fsi_enable_irq and
fsi_disable_irq.

Signed-off-by: Eddie James <eajames@us.ibm.com>
Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 73fdb69..ca3021f 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -973,12 +973,57 @@ void fsi_driver_unregister(struct fsi_driver *fsi_drv)
 
 int fsi_enable_irq(struct fsi_device *dev)
 {
+	int rc;
+	uint32_t si1m;
+	uint32_t bit = 0x80000000 >> dev->si1s_bit;
+	struct fsi_master *master = dev->slave->master;
+
+	if (!dev->irq_handler)
+		return -EINVAL;
+
+	rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+			sizeof(uint32_t));
+	if (rc) {
+		dev_err(&master->dev, "Coudn't read si1m:%d\n", rc);
+		return rc;
+	}
+
+	si1m |= bit;
+	rc = master->write(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+			sizeof(uint32_t));
+	if (rc) {
+		dev_err(&master->dev, "Coudn't write si1m:%d\n", rc);
+		return rc;
+	}
+
+	master->ipoll |= bit;
 	return 0;
 }
 EXPORT_SYMBOL(fsi_enable_irq);
 
 void fsi_disable_irq(struct fsi_device *dev)
 {
+	int rc;
+	uint32_t si1m;
+	uint32_t bits = ~(0x80000000 >> dev->si1s_bit);
+	struct fsi_master *master = dev->slave->master;
+
+	master->ipoll &= bits;
+
+	rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+			sizeof(uint32_t));
+	if (rc) {
+		dev_err(&master->dev, "Couldn't read si1m:%d\n", rc);
+		return;
+	}
+
+	si1m &= bits;
+	rc = master->write(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+		sizeof(uint32_t));
+	if (rc) {
+		dev_err(&master->dev, "Coudn't write si1m:%d\n", rc);
+		return;
+	}
 }
 EXPORT_SYMBOL(fsi_disable_irq);
 
-- 
1.8.2.2

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

* [PATCH linux dev-4.10 3/7] drivers/fsi: Scan for hub sourced IRQ's
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
  2017-05-09 21:38 ` [PATCH linux dev-4.10 1/7] drivers/fsi: Add slave interrupt polling Christopher Bostic
  2017-05-09 21:38 ` [PATCH linux dev-4.10 2/7] drivers/fsi: Add Client IRQ Enable / Disable Christopher Bostic
@ 2017-05-09 21:38 ` Christopher Bostic
  2017-05-09 21:38 ` [PATCH linux dev-4.10 4/7] drivers/fsi: Set IRQ masks along hub path Christopher Bostic
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:38 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Look for the hub link that may have sourced the IRQ being handled.
Clear out hub link interrupting conditions that are latched in
hardware after FSI client handler has been dispatched.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c       | 32 ++++++++++++---
 drivers/fsi/fsi-master-hub.c | 93 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/fsi/fsi-master.h     |  2 +
 3 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index ca3021f..d29af9a 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -54,6 +54,8 @@
 #define FSI_SSTAT		0x14	/* R  : Slave status */
 #define FSI_SI1M		0x18	/* R/W: IRQ mask */
 #define FSI_SI1S		0x1C	/* R  : IRQ status */
+#define FSI_SRSIC0		0x68	/* R/W: Hub IRQ condition 0 */
+#define FSI_SRSIC1		0x6C	/* R/W: Hub IRQ condition 1 */
 #define FSI_LLMODE		0x100	/* R/W: Link layer mode register */
 
 /*
@@ -573,6 +575,21 @@ static void fsi_slave_release(struct device *dev)
 	kfree(slave);
 }
 
+static int fsi_slave_irq_clear(struct fsi_slave *slave)
+{
+	uint32_t clear = ~0;
+	int rc;
+
+	rc = fsi_slave_write(slave, FSI_SLAVE_BASE + FSI_SRSIC0, &clear,
+				sizeof(clear));
+	if (rc) {
+		dev_dbg(&slave->dev, "Failed on write to SRSIC0\n");
+		return rc;
+	}
+	return fsi_slave_write(slave, FSI_SLAVE_BASE + FSI_SRSIC1, &clear,
+				sizeof(clear));
+}
+
 static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 {
 	uint32_t chip_id, llmode;
@@ -657,8 +674,11 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 	if (rc)
 		dev_warn(&slave->dev, "failed to create term attr: %d\n", rc);
 
-	fsi_slave_scan(slave);
-	return 0;
+	rc = fsi_slave_scan(slave);
+	if (rc)
+		return rc;
+
+	return fsi_slave_irq_clear(slave);
 }
 
 /* FSI master support */
@@ -774,6 +794,7 @@ static int __fsi_dev_irq(struct device *dev, void *data)
 {
 	uint32_t *si1s = data;
 	struct fsi_device *fsi_dev = to_fsi_dev(dev);
+	int rc;
 
 	if (!fsi_dev || !si1s) {
 		dev_dbg(dev, "Invalid input: %p %p\n", fsi_dev, si1s);
@@ -782,8 +803,8 @@ static int __fsi_dev_irq(struct device *dev, void *data)
 
 	if (*si1s & (0x80000000 >> fsi_dev->si1s_bit) &&
 					fsi_dev->irq_handler) {
-		fsi_dev->irq_handler(0, &fsi_dev->dev);
-		return 1;
+		rc = fsi_dev->irq_handler(0, &fsi_dev->dev);
+		dev_dbg(dev, "IRQ handler exit: %d\n", rc);
 	}
 
 	return 0;
@@ -794,7 +815,7 @@ static int __fsi_slave_irq(struct device *dev, void *data)
 	return device_for_each_child(dev, data, __fsi_dev_irq);
 }
 
-static void fsi_master_irq(struct fsi_master *master, int link, uint32_t si1s)
+void fsi_master_irq(struct fsi_master *master, int link, uint32_t si1s)
 {
 	device_for_each_child(&master->dev, &si1s, __fsi_slave_irq);
 }
@@ -817,6 +838,7 @@ static int fsi_master_ipoll(void *data)
 		if (rc)
 			goto done;
 
+		si1s = be32_to_cpu(si1s);
 		if (si1s & master->ipoll)
 			fsi_master_irq(master, 0, si1s);
 done:
diff --git a/drivers/fsi/fsi-master-hub.c b/drivers/fsi/fsi-master-hub.c
index 133b9bf..aebaa6b 100644
--- a/drivers/fsi/fsi-master-hub.c
+++ b/drivers/fsi/fsi-master-hub.c
@@ -20,6 +20,18 @@
 
 #include "fsi-master.h"
 
+/* Upstream Slave Hub Related Registers */
+#define FSI_SLAVE_BASE		0x800
+#define FSI_SI1S		0x1C		/* R:   IRQ status */
+#define FSI_SRSIC0		0x68		/* R/W: Hub IRQ condition 0 */
+#define FSI_SRSIC1		0x6C		/* R/W: Hub IRQ condition 1 */
+#define FSI_SRSIM0		0x70		/* R/W: Hub IRQ mask 0 */
+#define FSI_SRSIS0		0x78		/* R: Hub IRQ status 0 */
+
+/* SRSIS / SRSIM / SRSIC fields */
+#define FSI_SRSIX_IRQ1_MASK	0x00aaaaaa      /* SI1 IRQ sources */
+#define FSI_SRSIX_BITS_PER_LINK	8
+
 /* Control Registers */
 #define FSI_MMODE		0x0		/* R/W: mode */
 #define FSI_MDLYR		0x4		/* R/W: delay */
@@ -64,6 +76,7 @@
 #define FSI_MECTRL_P8_AUTO_TERM	0x4000		/* Auto terminate */
 
 #define FSI_ENGID_HUB_MASTER		0x1c
+#define FSI_HUB_UPSTREAM_SI1S_BIT	11
 #define FSI_HUB_LINK_OFFSET		0x80000
 #define FSI_HUB_LINK_SIZE		0x80000
 #define FSI_HUB_MASTER_MAX_LINKS	8
@@ -168,6 +181,83 @@ static inline u32 fsi_mmode_crs1(u32 x)
 	return (x & FSI_MMODE_CRS1MASK) << FSI_MMODE_CRS1SHFT;
 }
 
+/* TODO: Add support for hub links 4-7 */
+static int next_hub_irq_source(struct device *dev, uint32_t srsis)
+{
+	int index;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!(srsis & FSI_SRSIX_IRQ1_MASK)) {
+		dev_dbg(dev, "Unexpected IRQ source SRSIS:0x%08x\n",
+			srsis);
+		return -EINVAL;
+	}
+
+	/*
+	 * TODO: add a round robin scheduler to ensure we don't favor
+	 * lower hub link irq sources over others
+	 */
+	index = __clz(srsis);
+	dev_dbg(dev, "SRSIS:0x%08x index:%d\n", srsis, index);
+	return index / FSI_SRSIX_BITS_PER_LINK;
+}
+
+/*
+ * Interrupt handler for IRQs sourced from a hub FSI link
+ */
+int fsi_master_hub_irq_handler(int irq, void *device_data)
+{
+	int rc, hublink;
+	struct device *dev = device_data;
+	struct fsi_master_hub *hub = dev_get_drvdata(dev);
+	uint32_t srsis, si1s;
+
+	if (!hub)
+		return 1;
+
+	rc = fsi_slave_read(hub->upstream->slave, FSI_SLAVE_BASE + FSI_SRSIS0,
+			&srsis, sizeof(srsis));
+	if (rc) {
+		dev_dbg(dev, "Hub IRQ: Failed to read SRSIS\n");
+		return rc;
+	}
+	srsis = be32_to_cpu(srsis);
+	if (srsis) {
+		hublink = next_hub_irq_source(dev, srsis);
+		if (hublink < 0)
+			return 1;
+
+		if (!(&hub->master.dev))
+			return 0;
+
+		rc = hub_master_read(&hub->master, hublink, 0,
+				FSI_SLAVE_BASE + FSI_SI1S, &si1s,
+				sizeof(si1s));
+		if (rc) {
+			dev_dbg(dev,
+				"Hub IRQ: Failed to read hub slave si1s\n");
+			return 1;
+		}
+		si1s = be32_to_cpu(si1s);
+		fsi_master_irq(&hub->master, hublink, si1s);
+
+		/* Clear the interrupting condition */
+		srsis = 0xff000000 >> (hublink * FSI_SRSIX_BITS_PER_LINK);
+		srsis = be32_to_cpu(srsis);
+		rc =  fsi_slave_write(hub->upstream->slave,
+					FSI_SLAVE_BASE + FSI_SRSIC0,
+					&srsis, sizeof(srsis));
+		if (rc)
+			dev_dbg(dev,
+				"Hub IRQ: Failed on write to clear out SRSIC\n");
+	} else
+		dev_dbg(dev, "Hub IRQ: No SRSIS bits asserted\n");
+
+	return 1;
+}
+
 static int hub_master_init(struct fsi_master_hub *hub)
 {
 	struct fsi_device *dev = hub->upstream;
@@ -281,6 +371,9 @@ static int hub_master_probe(struct device *dev)
 	hub->master.send_break = hub_master_break;
 	hub->master.link_enable = hub_master_link_enable;
 
+	/* Override the parent slave's setting for si1s */
+	fsi_dev->si1s_bit = FSI_HUB_UPSTREAM_SI1S_BIT;
+	fsi_dev->irq_handler = fsi_master_hub_irq_handler;
 	dev_set_drvdata(dev, hub);
 
 	hub_master_init(hub);
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index 668ab0c..3334558 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -41,6 +41,8 @@ struct fsi_master {
 extern int fsi_master_register(struct fsi_master *master);
 extern void fsi_master_unregister(struct fsi_master *master);
 
+void fsi_master_irq(struct fsi_master *master, int link, uint32_t si1s);
+
 /**
  * crc4 helper: Given a starting crc4 state @c, calculate the crc4 vaue of @x,
  * which is @bits in length. This may be required by master implementations
-- 
1.8.2.2

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

* [PATCH linux dev-4.10 4/7] drivers/fsi: Set IRQ masks along hub path
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
                   ` (2 preceding siblings ...)
  2017-05-09 21:38 ` [PATCH linux dev-4.10 3/7] drivers/fsi: Scan for hub sourced IRQ's Christopher Bostic
@ 2017-05-09 21:38 ` Christopher Bostic
  2017-05-09 21:39 ` [PATCH linux dev-4.10 5/7] drivers/fsi: Unscan on master unregister Christopher Bostic
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:38 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Enable/disable client engine IRQ masks including those along
the hub path to a particular engine. This includes slave
Si1M, SRSIM, and hub master MSIEP, MMODE.

Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c       | 145 +++++++++++++++++++++++++++++++++++++++++--
 drivers/fsi/fsi-master-hub.c |   6 +-
 2 files changed, 144 insertions(+), 7 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index d29af9a..d6ea95b 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -56,6 +56,8 @@
 #define FSI_SI1S		0x1C	/* R  : IRQ status */
 #define FSI_SRSIC0		0x68	/* R/W: Hub IRQ condition 0 */
 #define FSI_SRSIC1		0x6C	/* R/W: Hub IRQ condition 1 */
+#define FSI_SRSIM0		0x70	/* R/W: Hub IRQ mask 0 */
+#define FSI_SRSIS0		0x78	/* R: Hub IRQ status 0 */
 #define FSI_LLMODE		0x100	/* R/W: Link layer mode register */
 
 /*
@@ -72,6 +74,13 @@
 #define FSI_SMODE_LBCRR_SHIFT	8		/* Clk ratio shift */
 #define FSI_SMODE_LBCRR_MASK	0xf		/* Clk ratio mask */
 
+#define FSI_SI1S_HUB_SRC	0x00100000
+
+/*
+ * SRSIM, SRSIS, SRSIC fields
+ */
+#define FSI_SRSIX_BITS_PER_LINK	8
+
 /*
  * LLMODE fields
  */
@@ -79,6 +88,12 @@
 
 #define FSI_SLAVE_SIZE_23b		0x800000
 
+/* Master control regs */
+#define	FSI_HUB_CONTROL		0x3400
+#define FSI_MMODE		0x0		/* R/W: mode */
+#define FSI_MSIEP0		0x30		/* R/W: Slave IRQ enable */
+#define FSI_MSIEP_BITS_PER_LINK	4
+
 static DEFINE_IDA(master_ida);
 
 struct fsi_slave {
@@ -807,7 +822,7 @@ static int __fsi_dev_irq(struct device *dev, void *data)
 		dev_dbg(dev, "IRQ handler exit: %d\n", rc);
 	}
 
-	return 0;
+	return 1;
 }
 
 static int __fsi_slave_irq(struct device *dev, void *data)
@@ -993,17 +1008,129 @@ void fsi_driver_unregister(struct fsi_driver *fsi_drv)
 }
 EXPORT_SYMBOL_GPL(fsi_driver_unregister);
 
+static uint32_t link_to_srsim_mask(int link)
+{
+	return ((0x80000000 >> 6) >> FSI_SRSIX_BITS_PER_LINK * link);
+}
+
+static uint32_t link_to_msiep_mask(int link)
+{
+	return (0xf0000000 >> (FSI_MSIEP_BITS_PER_LINK * link));
+}
+
+static int fsi_write_mask(struct fsi_master *master, struct fsi_slave *slave,
+			uint32_t offset, uint32_t mask, int on)
+{
+	int rc;
+	uint32_t val;
+
+	if (!slave && !master)
+		return -EINVAL;
+
+	if (slave)
+		rc = fsi_slave_read(slave, FSI_SLAVE_BASE + offset, &val,
+				sizeof(val));
+	else
+		rc = master->read(master, 0, 0, offset, &val, sizeof(val));
+
+	if (rc) {
+		dev_dbg(&slave->dev, "Failed to read offset %04x\n",
+			offset);
+		return rc;
+	}
+	val = be32_to_cpu(val);
+
+	if (on)
+		val |= mask;
+	else
+		val &= ~mask;
+
+	val = cpu_to_be32(val);
+	if (slave)
+		rc = fsi_slave_write(slave, FSI_SLAVE_BASE + offset, &val,
+				sizeof(val));
+	else
+		rc = master->write(master, 0, 0, offset, &val, sizeof(val));
+
+	return rc;
+}
+
+static int set_upstream_irq_masks(struct fsi_master *master,
+			struct fsi_slave *slave, int on)
+{
+	struct fsi_slave *upstream_slave;
+	struct fsi_master *upstream_master;
+	uint32_t mask, si1m;
+	int rc;
+
+	if (!master->idx)
+		return 0;
+
+	upstream_slave = to_fsi_slave(slave->master->dev.parent);
+	if (!upstream_slave) {
+		dev_dbg(&slave->dev, "No upstream slave found\n");
+		return -ENODEV;
+	}
+
+	mask = link_to_srsim_mask(slave->link);
+	rc = fsi_write_mask(NULL, upstream_slave, FSI_SRSIM0, mask, on);
+	if (rc)
+		return rc;
+
+	upstream_master = upstream_slave->master;
+	if (!upstream_master) {
+		dev_dbg(&upstream_slave->dev, "Cannot find master\n");
+		return -ENODEV;
+	}
+
+	mask = link_to_msiep_mask(slave->link);
+
+	/*
+	 * TODO: Remove these HUB control references by creating a new master
+	 * method master->write_control(msiep)
+	 */
+	rc = fsi_write_mask(upstream_master, NULL, FSI_HUB_CONTROL + FSI_MSIEP0,
+			mask, on);
+
+	mask = FSI_SI1S_HUB_SRC;
+	if (on)
+		upstream_master->ipoll |= mask;
+	else
+		upstream_master->ipoll &= mask;
+
+	if (rc)
+		return rc;
+
+	si1m = be32_to_cpu(0xd0040410);
+
+	/*
+	 * TODO: Remove the HUB control reference by creating a new master
+	 * method master->write_control(mmode)
+	 */
+	rc = upstream_master->write(upstream_master, 0, 0,
+			FSI_HUB_CONTROL + FSI_MMODE, &si1m,
+			sizeof(si1m));
+	if (rc) {
+		dev_dbg(&upstream_slave->dev,
+			"Failed to set i-poll\n");
+	}
+
+	return fsi_write_mask(NULL, upstream_slave, FSI_SI1M, mask, on);
+}
+
 int fsi_enable_irq(struct fsi_device *dev)
 {
 	int rc;
 	uint32_t si1m;
 	uint32_t bit = 0x80000000 >> dev->si1s_bit;
 	struct fsi_master *master = dev->slave->master;
+	struct fsi_slave *slave = dev->slave;
+	int link = slave->link;
 
 	if (!dev->irq_handler)
 		return -EINVAL;
 
-	rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+	rc = master->read(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
 			sizeof(uint32_t));
 	if (rc) {
 		dev_err(&master->dev, "Coudn't read si1m:%d\n", rc);
@@ -1011,7 +1138,7 @@ int fsi_enable_irq(struct fsi_device *dev)
 	}
 
 	si1m |= bit;
-	rc = master->write(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+	rc = master->write(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
 			sizeof(uint32_t));
 	if (rc) {
 		dev_err(&master->dev, "Coudn't write si1m:%d\n", rc);
@@ -1019,20 +1146,23 @@ int fsi_enable_irq(struct fsi_device *dev)
 	}
 
 	master->ipoll |= bit;
-	return 0;
+	return set_upstream_irq_masks(master, slave, 1);
 }
 EXPORT_SYMBOL(fsi_enable_irq);
 
+
 void fsi_disable_irq(struct fsi_device *dev)
 {
 	int rc;
 	uint32_t si1m;
 	uint32_t bits = ~(0x80000000 >> dev->si1s_bit);
 	struct fsi_master *master = dev->slave->master;
+	struct fsi_slave *slave = dev->slave;
+	int link = slave->link;
 
 	master->ipoll &= bits;
 
-	rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+	rc = master->read(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
 			sizeof(uint32_t));
 	if (rc) {
 		dev_err(&master->dev, "Couldn't read si1m:%d\n", rc);
@@ -1040,12 +1170,15 @@ void fsi_disable_irq(struct fsi_device *dev)
 	}
 
 	si1m &= bits;
-	rc = master->write(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
+	rc = master->write(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
 		sizeof(uint32_t));
 	if (rc) {
 		dev_err(&master->dev, "Coudn't write si1m:%d\n", rc);
 		return;
 	}
+
+	if (!master->ipoll)
+		set_upstream_irq_masks(master, slave, 0);
 }
 EXPORT_SYMBOL(fsi_disable_irq);
 
diff --git a/drivers/fsi/fsi-master-hub.c b/drivers/fsi/fsi-master-hub.c
index aebaa6b..48944b6 100644
--- a/drivers/fsi/fsi-master-hub.c
+++ b/drivers/fsi/fsi-master-hub.c
@@ -59,7 +59,11 @@
 #define FSI_MMODE_CRS1SHFT	8		/* Clk rate selection 1 shift */
 #define FSI_MMODE_CRS1MASK	0x3ff		/* Clk rate selection 1 mask */
 
-/* MRESB: Reset brindge */
+/* MSIEP: Per slave interrupt enable */
+#define FSI_MSIEP0		0x30		/* R/W: Slave IRQ enable */
+#define FSI_MSIEP_BITS_PER_LINK 4
+
+/* MRESB: Reset bridge */
 #define FSI_MRESB_RST_GEN	0x80000000	/* General reset */
 #define FSI_MRESB_RST_ERR	0x40000000	/* Error Reset */
 
-- 
1.8.2.2

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

* [PATCH linux dev-4.10 5/7] drivers/fsi: Unscan on master unregister
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
                   ` (3 preceding siblings ...)
  2017-05-09 21:38 ` [PATCH linux dev-4.10 4/7] drivers/fsi: Set IRQ masks along hub path Christopher Bostic
@ 2017-05-09 21:39 ` Christopher Bostic
  2017-05-11 12:06   ` Joel Stanley
  2017-05-09 21:39 ` [PATCH linux dev-4.10 6/7] drivers/fsi: GPIO stability changes for Cronus/Hostboot Christopher Bostic
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:39 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Unscan all devices whatn a master unregisters - ensures full
cleanup.

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

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index d6ea95b..809a3c4 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -965,6 +965,7 @@ void fsi_master_unregister(struct fsi_master *master)
 		master_ipoll = NULL;
 	}
 
+	fsi_master_unscan(master);
 	device_unregister(&master->dev);
 }
 EXPORT_SYMBOL_GPL(fsi_master_unregister);
-- 
1.8.2.2

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

* [PATCH linux dev-4.10 6/7] drivers/fsi: GPIO stability changes for Cronus/Hostboot
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
                   ` (4 preceding siblings ...)
  2017-05-09 21:39 ` [PATCH linux dev-4.10 5/7] drivers/fsi: Unscan on master unregister Christopher Bostic
@ 2017-05-09 21:39 ` Christopher Bostic
  2017-05-11 12:07   ` Joel Stanley
  2017-05-09 21:39 ` [PATCH linux dev-4.10 7/7] drivers/fsi: Fix one and two byte bus reads/writes Christopher Bostic
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:39 UTC (permalink / raw)
  To: joel; +Cc: Christopher Bostic, openbmc

Improve stability in the FSI protocol by re-ordering the clocking
delays. Increase clocking delays to 3 microseconds.  Remove
delay prior to sampling input - now redundant given new clocking
delay order.

New effective delay per clock toggle is now 6 microseconds.
Previous clocking summed up to 3 nS but real time measurements
of each 1 nS delay actually was approx 1.8 microseconds.
Previous total delay was then 1.8 * 3 = 5.4 microseconds.

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

diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index d5cce88..ef209ef 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -14,7 +14,7 @@
 
 #include "fsi-master.h"
 
-#define	FSI_GPIO_STD_DLY	1	/* Standard pin delay in nS */
+#define	FSI_GPIO_STD_DLY	3	/* Standard pin delay in uS */
 #define	FSI_ECHO_DELAY_CLOCKS	16	/* Number clocks for echo delay */
 #define	FSI_PRE_BREAK_CLOCKS	50	/* Number clocks to prep for break */
 #define	FSI_BREAK_CLOCKS	256	/* Number of clocks to issue break */
@@ -76,10 +76,10 @@ static void clock_toggle(struct fsi_master_gpio *master, int count)
 	int i;
 
 	for (i = 0; i < count; i++) {
-		ndelay(FSI_GPIO_STD_DLY);
 		gpiod_set_value(master->gpio_clk, 0);
-		ndelay(FSI_GPIO_STD_DLY);
+		udelay(FSI_GPIO_STD_DLY);
 		gpiod_set_value(master->gpio_clk, 1);
+		udelay(FSI_GPIO_STD_DLY);
 	}
 }
 
@@ -87,7 +87,6 @@ static int sda_in(struct fsi_master_gpio *master)
 {
 	int in;
 
-	ndelay(FSI_GPIO_STD_DLY);
 	in = gpiod_get_value(master->gpio_data);
 	return in ? 1 : 0;
 }
-- 
1.8.2.2

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

* [PATCH linux dev-4.10 7/7] drivers/fsi: Fix one and two byte bus reads/writes
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
                   ` (5 preceding siblings ...)
  2017-05-09 21:39 ` [PATCH linux dev-4.10 6/7] drivers/fsi: GPIO stability changes for Cronus/Hostboot Christopher Bostic
@ 2017-05-09 21:39 ` Christopher Bostic
  2017-05-11 12:06   ` Joel Stanley
  2017-05-10  2:25 ` [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Jeremy Kerr
  2017-05-11 12:09 ` Joel Stanley
  8 siblings, 1 reply; 15+ messages in thread
From: Christopher Bostic @ 2017-05-09 21:39 UTC (permalink / raw)
  To: joel; +Cc: Eddie James, openbmc, Christopher Bostic

From: Eddie James <eajames@us.ibm.com>

Address checker fixed to allow one and two byte reads/writes.
Address alignments for each size verified.

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

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 809a3c4..2a65aa6 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -699,10 +699,13 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 /* FSI master support */
 static int fsi_check_access(uint32_t addr, size_t size)
 {
-	if (size != 1 && size != 2 && size != 4)
-		return -EINVAL;
-
-	if ((addr & 0x3) != (size & 0x3))
+	if (size == 4) {
+		if (addr & 0x3)
+			return -EINVAL;
+	} else if (size == 2) {
+		if (addr & 0x1)
+			return -EINVAL;
+	} else if (size != 1)
 		return -EINVAL;
 
 	return 0;
-- 
1.8.2.2

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

* Re: [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
                   ` (6 preceding siblings ...)
  2017-05-09 21:39 ` [PATCH linux dev-4.10 7/7] drivers/fsi: Fix one and two byte bus reads/writes Christopher Bostic
@ 2017-05-10  2:25 ` Jeremy Kerr
  2017-05-10 15:46   ` Christopher Bostic
  2017-05-11 12:09 ` Joel Stanley
  8 siblings, 1 reply; 15+ messages in thread
From: Jeremy Kerr @ 2017-05-10  2:25 UTC (permalink / raw)
  To: Christopher Bostic, joel; +Cc: openbmc

Hi Chris,

If (and only if) you're planning to send another revision of the fsi
patches upstream, I'd suggest squashing these into their original
commits:

>   drivers/fsi: Unscan on master unregister
>   drivers/fsi: Fix one and two byte bus reads/writes

But if not, I'm happy for these to stay separate.

Other than that, this series should be fine for the openbmc tree.

Cheers,


Jeremy

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

* Re: [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel
  2017-05-10  2:25 ` [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Jeremy Kerr
@ 2017-05-10 15:46   ` Christopher Bostic
  0 siblings, 0 replies; 15+ messages in thread
From: Christopher Bostic @ 2017-05-10 15:46 UTC (permalink / raw)
  To: Jeremy Kerr, joel; +Cc: openbmc



On 5/9/17 9:25 PM, Jeremy Kerr wrote:
> Hi Chris,
>
> If (and only if) you're planning to send another revision of the fsi
> patches upstream, I'd suggest squashing these into their original
> commits:
>
>>    drivers/fsi: Unscan on master unregister
>>    drivers/fsi: Fix one and two byte bus reads/writes
> But if not, I'm happy for these to stay separate.

Hi Jeremy,

Yep, I have that squashed into the v7 set.

Thanks,
Chris

> Other than that, this series should be fine for the openbmc tree.
>
> Cheers,
>
>
> Jeremy
>

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

* Re: [PATCH linux dev-4.10 1/7] drivers/fsi: Add slave interrupt polling
  2017-05-09 21:38 ` [PATCH linux dev-4.10 1/7] drivers/fsi: Add slave interrupt polling Christopher Bostic
@ 2017-05-10 22:26   ` Eddie James
  0 siblings, 0 replies; 15+ messages in thread
From: Eddie James @ 2017-05-10 22:26 UTC (permalink / raw)
  To: Christopher Bostic, joel; +Cc: Eddie James, openbmc



On 05/09/2017 04:38 PM, Christopher Bostic wrote:
> Scan slaves present for asserting interrupt signals in the
> si1s register and call a registered client's interrupt handler as
> appropriate.
>
> Includes initial code from Eddie James <eajames@us.ibm.com>
>
> Signed-off-by: Eddie James <eajames@us.ibm.com>
> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
> ---
>   drivers/fsi/fsi-core.c   | 110 +++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/fsi/fsi-master.h |   1 +
>   include/linux/fsi.h      |   5 +++
>   3 files changed, 116 insertions(+)
>
> diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
> index a6ed34f..73fdb69 100644
> --- a/drivers/fsi/fsi-core.c
> +++ b/drivers/fsi/fsi-core.c
> @@ -15,9 +15,11 @@
>
>   #include <linux/device.h>
>   #include <linux/fsi.h>
> +#include <linux/kthread.h>
>   #include <linux/idr.h>
>   #include <linux/module.h>
>   #include <linux/slab.h>
> +#include <linux/jiffies.h>
>
>   #include "fsi-master.h"
>
> @@ -38,8 +40,11 @@
>   #define FSI_PEEK_BASE			0x410
>
>   static const int engine_page_size = 0x400;
> +static struct task_struct *master_ipoll;
> +static unsigned int fsi_ipoll_period_ms = 100;
>
>   #define FSI_SLAVE_BASE			0x800
> +#define FSI_IPOLL_PERIOD		msecs_to_jiffies(fsi_ipoll_period_ms)
>
>   /*
>    * FSI slave engine control register offsets
> @@ -47,6 +52,8 @@
>   #define FSI_SMODE		0x0	/* R/W: Mode register */
>   #define FSI_SISC		0x8	/* R/W: Interrupt condition */
>   #define FSI_SSTAT		0x14	/* R  : Slave status */
> +#define FSI_SI1M		0x18	/* R/W: IRQ mask */
> +#define FSI_SI1S		0x1C	/* R  : IRQ status */
>   #define FSI_LLMODE		0x100	/* R/W: Link layer mode register */
>
>   /*
> @@ -342,6 +349,7 @@ static int fsi_slave_scan(struct fsi_slave *slave)
>   	uint32_t engine_addr;
>   	uint32_t conf;
>   	int rc, i;
> +	uint8_t si1s_bit = 1;
>
>   	/*
>   	 * scan engines
> @@ -396,6 +404,7 @@ static int fsi_slave_scan(struct fsi_slave *slave)
>   			dev->unit = i;
>   			dev->addr = engine_addr;
>   			dev->size = slots * engine_page_size;
> +			dev->si1s_bit = si1s_bit++;
>
>   			dev_info(&slave->dev,
>   			"engine[%i]: type %x, version %x, addr %x size %x\n",
> @@ -761,6 +770,90 @@ static void fsi_master_unscan(struct fsi_master *master)
>   	device_for_each_child(&master->dev, NULL, __fsi_master_remove_slave);
>   }
>
> +static int __fsi_dev_irq(struct device *dev, void *data)
> +{
> +	uint32_t *si1s = data;
> +	struct fsi_device *fsi_dev = to_fsi_dev(dev);
> +
> +	if (!fsi_dev || !si1s) {
> +		dev_dbg(dev, "Invalid input: %p %p\n", fsi_dev, si1s);
> +		return -EINVAL;
> +	}
> +
> +	if (*si1s & (0x80000000 >> fsi_dev->si1s_bit) &&
> +					fsi_dev->irq_handler) {
> +		fsi_dev->irq_handler(0, &fsi_dev->dev);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int __fsi_slave_irq(struct device *dev, void *data)
> +{
> +	return device_for_each_child(dev, data, __fsi_dev_irq);
> +}
> +
> +static void fsi_master_irq(struct fsi_master *master, int link, uint32_t si1s)
> +{
> +	device_for_each_child(&master->dev, &si1s, __fsi_slave_irq);
> +}
> +
> +static int fsi_master_ipoll(void *data)
> +{
> +	int rc;
> +	uint32_t si1s;
> +	unsigned long elapsed = 0;
> +	unsigned long previous_jiffies = jiffies;
> +	struct fsi_master *master = data;
> +
> +	while (!kthread_should_stop()) {
> +		if (!master->ipoll)
> +			goto done;
> +
> +		/* Ignore errors for now */
> +		rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1S,
> +				&si1s, sizeof(uint32_t));
> +		if (rc)
> +			goto done;
> +
> +		if (si1s & master->ipoll)
> +			fsi_master_irq(master, 0, si1s);
> +done:
> +		elapsed = jiffies = previous_jiffies;
> +		if (elapsed < FSI_IPOLL_PERIOD) {
> +			set_current_state(TASK_UNINTERRUPTIBLE);
> +			schedule_timeout(FSI_IPOLL_PERIOD - elapsed);
> +		}
> +		previous_jiffies = jiffies;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * TODO: move this to master->start_ipoll() - each master may have its
> + * own way of doing this
> + */
> +int fsi_master_start_ipoll(struct fsi_master *master)
> +{
> +	if (master_ipoll) {
> +		dev_err(&master->dev, "Already polling for irqs\n");
> +		return -EALREADY;
> +	}
> +	master_ipoll = kthread_create(fsi_master_ipoll, master,
> +					"fsi_master_ipoll");
> +	if (IS_ERR(master_ipoll)) {
> +		dev_err(&master->dev, "Coudn't create ipoll thread rc:%d\n",
> +			(int)PTR_ERR(master_ipoll));
> +		return PTR_ERR(master_ipoll);
> +	}
> +	wake_up_process(master_ipoll);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(fsi_master_start_ipoll);
> +
>   static ssize_t master_rescan_store(struct device *dev,
>   		struct device_attribute *attr, const char *buf, size_t count)
>   {
> @@ -768,6 +861,7 @@ static ssize_t master_rescan_store(struct device *dev,
>
>   	fsi_master_unscan(master);
>   	fsi_master_scan(master);
> +	fsi_master_start_ipoll(master);

I have been having some problems in 4.10 with this patch in the build. 
BMC is hanging and requires AC cycle to recover, directly after scanning 
fsi. I haven't had time to debug but so far it seems to follow this 
patch. I do not think this should be merged until Chris and I have done 
more testing.

Thanks,
Eddie

>
>   	return count;
>   }
> @@ -829,6 +923,11 @@ void fsi_master_unregister(struct fsi_master *master)
>   		master->idx = -1;
>   	}
>
> +	if (master_ipoll) {
> +		kthread_stop(master_ipoll);
> +		master_ipoll = NULL;
> +	}
> +
>   	device_unregister(&master->dev);
>   }
>   EXPORT_SYMBOL_GPL(fsi_master_unregister);
> @@ -872,6 +971,17 @@ void fsi_driver_unregister(struct fsi_driver *fsi_drv)
>   }
>   EXPORT_SYMBOL_GPL(fsi_driver_unregister);
>
> +int fsi_enable_irq(struct fsi_device *dev)
> +{
> +	return 0;
> +}
> +EXPORT_SYMBOL(fsi_enable_irq);
> +
> +void fsi_disable_irq(struct fsi_device *dev)
> +{
> +}
> +EXPORT_SYMBOL(fsi_disable_irq);
> +
>   struct bus_type fsi_bus_type = {
>   	.name		= "fsi",
>   	.match		= fsi_bus_match,
> diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
> index fd39924..668ab0c 100644
> --- a/drivers/fsi/fsi-master.h
> +++ b/drivers/fsi/fsi-master.h
> @@ -26,6 +26,7 @@ struct fsi_master {
>   	int		idx;
>   	int		n_links;
>   	int		flags;
> +	uint32_t	ipoll;
>   	int		(*read)(struct fsi_master *, int link, uint8_t id,
>   				uint32_t addr, void *val, size_t size);
>   	int		(*write)(struct fsi_master *, int link, uint8_t id,
> diff --git a/include/linux/fsi.h b/include/linux/fsi.h
> index 141fd38..bb5c6c6 100644
> --- a/include/linux/fsi.h
> +++ b/include/linux/fsi.h
> @@ -22,9 +22,11 @@ struct fsi_device {
>   	u8			engine_type;
>   	u8			version;
>   	u8			unit;
> +	u8			si1s_bit;
>   	struct fsi_slave	*slave;
>   	uint32_t		addr;
>   	uint32_t		size;
> +	int (*irq_handler)(int, void *);
>   };
>
>   extern int fsi_device_read(struct fsi_device *dev, uint32_t addr,
> @@ -80,4 +82,7 @@ extern int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
>
>   extern struct bus_type fsi_bus_type;
>
> +extern int fsi_enable_irq(struct fsi_device *dev);
> +extern void fsi_disable_irq(struct fsi_device *dev);
> +
>   #endif /* LINUX_FSI_H */

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

* Re: [PATCH linux dev-4.10 7/7] drivers/fsi: Fix one and two byte bus reads/writes
  2017-05-09 21:39 ` [PATCH linux dev-4.10 7/7] drivers/fsi: Fix one and two byte bus reads/writes Christopher Bostic
@ 2017-05-11 12:06   ` Joel Stanley
  0 siblings, 0 replies; 15+ messages in thread
From: Joel Stanley @ 2017-05-11 12:06 UTC (permalink / raw)
  To: Christopher Bostic; +Cc: Eddie James, OpenBMC Maillist

On Wed, May 10, 2017 at 7:09 AM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> From: Eddie James <eajames@us.ibm.com>
>
> Address checker fixed to allow one and two byte reads/writes.
> Address alignments for each size verified.
>
> Signed-off-by: Edward James <eajames@us.ibm.com>
> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>

Applied to dev-4.10.

Cheers,

Joel

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

* Re: [PATCH linux dev-4.10 5/7] drivers/fsi: Unscan on master unregister
  2017-05-09 21:39 ` [PATCH linux dev-4.10 5/7] drivers/fsi: Unscan on master unregister Christopher Bostic
@ 2017-05-11 12:06   ` Joel Stanley
  0 siblings, 0 replies; 15+ messages in thread
From: Joel Stanley @ 2017-05-11 12:06 UTC (permalink / raw)
  To: Christopher Bostic; +Cc: OpenBMC Maillist

On Wed, May 10, 2017 at 7:09 AM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> Unscan all devices whatn a master unregisters - ensures full
> cleanup.
>
> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>

Applied to dev-4.10.

Cheers,

Joel

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

* Re: [PATCH linux dev-4.10 6/7] drivers/fsi: GPIO stability changes for Cronus/Hostboot
  2017-05-09 21:39 ` [PATCH linux dev-4.10 6/7] drivers/fsi: GPIO stability changes for Cronus/Hostboot Christopher Bostic
@ 2017-05-11 12:07   ` Joel Stanley
  0 siblings, 0 replies; 15+ messages in thread
From: Joel Stanley @ 2017-05-11 12:07 UTC (permalink / raw)
  To: Christopher Bostic; +Cc: OpenBMC Maillist

On Wed, May 10, 2017 at 7:09 AM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> Improve stability in the FSI protocol by re-ordering the clocking
> delays. Increase clocking delays to 3 microseconds.  Remove
> delay prior to sampling input - now redundant given new clocking
> delay order.
>
> New effective delay per clock toggle is now 6 microseconds.
> Previous clocking summed up to 3 nS but real time measurements
> of each 1 nS delay actually was approx 1.8 microseconds.
> Previous total delay was then 1.8 * 3 = 5.4 microseconds.
>
> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>

Applied to dev-4.10 with a note about this being a temporary fix until
we find the root cause.

Keep us updated with the investigation.

Cheers,

Joel

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

* Re: [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel
  2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
                   ` (7 preceding siblings ...)
  2017-05-10  2:25 ` [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Jeremy Kerr
@ 2017-05-11 12:09 ` Joel Stanley
  8 siblings, 0 replies; 15+ messages in thread
From: Joel Stanley @ 2017-05-11 12:09 UTC (permalink / raw)
  To: Christopher Bostic; +Cc: OpenBMC Maillist

On Wed, May 10, 2017 at 7:08 AM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> These changes bring the 4.10 kernel FSI device driver up to date
> with the 4.7 kernel version.
>
> * Add basic and hub interrupt support
> * Bug fixes introduced during 4.7 to 4.10 migration
> * FSI protocol modification for added operational stability
>
> Christopher Bostic (5):
>   drivers/fsi: Add slave interrupt polling
>   drivers/fsi: Scan for hub sourced IRQ's
>   drivers/fsi: Set IRQ masks along hub path
>   drivers/fsi: Add Client IRQ Enable / Disable

As discussed we will hold off on these until the stability issues are resolved.

>   drivers/fsi: Unscan on master unregister
>   drivers/fsi: GPIO stability changes for Cronus/Hostboot
>   drivers/fsi: Fix one and two byte bus reads/writes

These three have been applied.

Cheers,

Joel

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

end of thread, other threads:[~2017-05-11 12:10 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-09 21:38 [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Christopher Bostic
2017-05-09 21:38 ` [PATCH linux dev-4.10 1/7] drivers/fsi: Add slave interrupt polling Christopher Bostic
2017-05-10 22:26   ` Eddie James
2017-05-09 21:38 ` [PATCH linux dev-4.10 2/7] drivers/fsi: Add Client IRQ Enable / Disable Christopher Bostic
2017-05-09 21:38 ` [PATCH linux dev-4.10 3/7] drivers/fsi: Scan for hub sourced IRQ's Christopher Bostic
2017-05-09 21:38 ` [PATCH linux dev-4.10 4/7] drivers/fsi: Set IRQ masks along hub path Christopher Bostic
2017-05-09 21:39 ` [PATCH linux dev-4.10 5/7] drivers/fsi: Unscan on master unregister Christopher Bostic
2017-05-11 12:06   ` Joel Stanley
2017-05-09 21:39 ` [PATCH linux dev-4.10 6/7] drivers/fsi: GPIO stability changes for Cronus/Hostboot Christopher Bostic
2017-05-11 12:07   ` Joel Stanley
2017-05-09 21:39 ` [PATCH linux dev-4.10 7/7] drivers/fsi: Fix one and two byte bus reads/writes Christopher Bostic
2017-05-11 12:06   ` Joel Stanley
2017-05-10  2:25 ` [PATCH linux dev-4.10 0/7] OpenFSI Updates for dev-4.10 kernel Jeremy Kerr
2017-05-10 15:46   ` Christopher Bostic
2017-05-11 12:09 ` Joel Stanley

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.