kernel: Patch in i2c, sbefifo, and occ drivers

Change-Id: I845752ca9f64f42f1fc46e14cac90a48f7195ca3
Signed-off-by: Edward A. James <eajames@us.ibm.com>
diff --git a/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-4-6-drivers-i2c-Add-I2C-master-locking-to-FSI-algorithm.patch b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-4-6-drivers-i2c-Add-I2C-master-locking-to-FSI-algorithm.patch
new file mode 100644
index 0000000..e649d62
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-obmc/linux-dev-4.10-v2-4-6-drivers-i2c-Add-I2C-master-locking-to-FSI-algorithm.patch
@@ -0,0 +1,112 @@
+From patchwork Wed May 10 15:52:40 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [linux, dev-4.10, v2,
+ 4/6] drivers: i2c: Add I2C master locking to FSI algorithm
+From: eajames@linux.vnet.ibm.com
+X-Patchwork-Id: 760699
+Message-Id: <1494431562-25101-5-git-send-email-eajames@linux.vnet.ibm.com>
+To: openbmc@lists.ozlabs.org
+Cc: "Edward A. James" <eajames@us.ibm.com>, cbostic@linux.vnet.ibm.com
+Date: Wed, 10 May 2017 10:52:40 -0500
+
+From: "Edward A. James" <eajames@us.ibm.com>
+
+Since there are many ports per master, each with it's own adapter and
+chardev, we need some locking to prevent xfers from changing the master
+state while other xfers are in progress.
+
+Signed-off-by: Edward A. James <eajames@us.ibm.com>
+---
+ drivers/i2c/busses/i2c-fsi.c | 41 +++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 37 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
+index f690b16..d757aee 100644
+--- a/drivers/i2c/busses/i2c-fsi.c
++++ b/drivers/i2c/busses/i2c-fsi.c
+@@ -136,6 +136,8 @@ struct fsi_i2c_master {
+ 	u8			fifo_size;
+ 	struct list_head	ports;
+ 	struct ida		ida;
++	wait_queue_head_t	wait;
++	struct semaphore	lock;
+ };
+ 
+ struct fsi_i2c_port {
+@@ -171,6 +173,29 @@ static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg,
+ 	return fsi_device_write(fsi, reg, &raw_data, sizeof(raw_data));
+ }
+ 
++static int fsi_i2c_lock_master(struct fsi_i2c_master *i2c, int timeout)
++{
++	int rc;
++
++	rc = down_trylock(&i2c->lock);
++	if (!rc)
++		return 0;
++
++	rc = wait_event_interruptible_timeout(i2c->wait,
++					      !down_trylock(&i2c->lock),
++					      timeout);
++	if (rc > 0)
++		return 0;
++
++	return -EBUSY;
++}
++
++static void fsi_i2c_unlock_master(struct fsi_i2c_master *i2c)
++{
++	up(&i2c->lock);
++	wake_up(&i2c->wait);
++}
++
+ static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c)
+ {
+ 	int rc;
+@@ -410,25 +435,31 @@ static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ 	struct fsi_i2c_port *port = adap->algo_data;
+ 	struct i2c_msg *msg;
+ 
+-	rc = fsi_i2c_set_port(port);
++	rc = fsi_i2c_lock_master(port->master, adap->timeout);
+ 	if (rc)
+ 		return rc;
+ 
++	rc = fsi_i2c_set_port(port);
++	if (rc)
++		goto unlock;
++
+ 	for (i = 0; i < num; ++i) {
+ 		msg = msgs + i;
+ 		start_time = jiffies;
+ 
+ 		rc = fsi_i2c_start(port, msg, i == num - 1);
+ 		if (rc)
+-			return rc;
++			goto unlock;
+ 
+ 		rc = fsi_i2c_wait(port, msg,
+ 				  adap->timeout - (jiffies - start_time));
+ 		if (rc)
+-			return rc;
++			goto unlock;
+ 	}
+ 
+-	return 0;
++unlock:
++	fsi_i2c_unlock_master(port->master);
++	return rc;
+ }
+ 
+ static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
+@@ -453,6 +484,8 @@ static int fsi_i2c_probe(struct device *dev)
+ 	if (!i2c)
+ 		return -ENOMEM;
+ 
++	init_waitqueue_head(&i2c->wait);
++	sema_init(&i2c->lock, 1);
+ 	i2c->fsi = to_fsi_dev(dev);
+ 	i2c->idx = ida_simple_get(&fsi_i2c_ida, 1, INT_MAX, GFP_KERNEL);
+ 	ida_init(&i2c->ida);