Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1681865 > unrolled thread

[PATCH v2 0/5] drivers/fsi: Add SBEFIFO and OCC drivers

Started byEddie James <eajames@linux.vnet.ibm.com>
First post2017-07-05 23:40 +0200
Last post2017-07-12 19:30 +0200
Articles 3 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/5] drivers/fsi: Add SBEFIFO and OCC drivers Eddie James <eajames@linux.vnet.ibm.com> - 2017-07-05 23:40 +0200
    [PATCH v2 2/5] drivers/fsi/sbefifo: Add in-kernel API Eddie James <eajames@linux.vnet.ibm.com> - 2017-07-05 23:40 +0200
      Re: [PATCH v2 2/5] drivers/fsi/sbefifo: Add in-kernel API kbuild test robot <lkp@intel.com> - 2017-07-12 19:30 +0200

#1681865 — [PATCH v2 0/5] drivers/fsi: Add SBEFIFO and OCC drivers

FromEddie James <eajames@linux.vnet.ibm.com>
Date2017-07-05 23:40 +0200
Subject[PATCH v2 0/5] drivers/fsi: Add SBEFIFO and OCC drivers
Message-ID<u00bE-3nZ-7@gated-at.bofh.it>
From: "Edward A. James" <eajames@us.ibm.com>

This series adds two FSI-based device drivers. The OCC driver is dependent on
the SBEFIFO driver, as a user of it's in-kernel API. The in-kernel API provided
by the OCC driver will be used by a hwmon driver (on the lkml as "Add On-Chip
Controller (OCC) hwmon driver").

Changes since v1:
 * Split bindings into separate patch and added SBEFIFO device binding
 * Fixed #includes
 * Fix SBEFIFO race condition between write() and poll_timer().
 * Followed Rob's suggestion to just create one platform device for hwmon
   driver, instead of using the device tree.
 * Also check for "command in progress" response from OCC and try a while

Edward A. James (5):
  drivers/fsi: Add SBEFIFO FSI client device driver
  drivers/fsi/sbefifo: Add in-kernel API
  drivers/fsi: Add On-Chip Controller (OCC) driver
  drivers/fsi/occ: Add in-kernel API
  Documentation/devicetree/bindings: Add FSI device documentation

 .../devicetree/bindings/fsi/ibm,p9-occ.txt         |  15 +
 .../devicetree/bindings/fsi/ibm,p9-sbefifo.txt     |  20 +
 drivers/fsi/Kconfig                                |  17 +
 drivers/fsi/Makefile                               |   2 +
 drivers/fsi/fsi-sbefifo.c                          | 932 +++++++++++++++++++++
 drivers/fsi/occ.c                                  | 803 ++++++++++++++++++
 include/linux/fsi-sbefifo.h                        |  30 +
 include/linux/occ.h                                |  41 +
 8 files changed, 1860 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fsi/ibm,p9-occ.txt
 create mode 100644 Documentation/devicetree/bindings/fsi/ibm,p9-sbefifo.txt
 create mode 100644 drivers/fsi/fsi-sbefifo.c
 create mode 100644 drivers/fsi/occ.c
 create mode 100644 include/linux/fsi-sbefifo.h
 create mode 100644 include/linux/occ.h

-- 
1.8.3.1

[toc] | [next] | [standalone]


#1681869 — [PATCH v2 2/5] drivers/fsi/sbefifo: Add in-kernel API

FromEddie James <eajames@linux.vnet.ibm.com>
Date2017-07-05 23:40 +0200
Subject[PATCH v2 2/5] drivers/fsi/sbefifo: Add in-kernel API
Message-ID<u00bF-3nZ-49@gated-at.bofh.it>
In reply to#1681865
From: "Edward A. James" <eajames@us.ibm.com>

Refactor the user interface of the SBEFIFO driver to allow for an
in-kernel read/write API. Add exported functions for other drivers to
call, and add an include file with those functions. Also parse the
device tree for child nodes and create child platform devices
accordingly.

Signed-off-by: Edward A. James <eajames@us.ibm.com>
---
 drivers/fsi/fsi-sbefifo.c   | 142 +++++++++++++++++++++++++++++++++++++-------
 include/linux/fsi-sbefifo.h |  30 ++++++++++
 2 files changed, 151 insertions(+), 21 deletions(-)
 create mode 100644 include/linux/fsi-sbefifo.h

diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 6915f5e..e0ddc5d 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -15,12 +15,16 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/fsi.h>
+#include <linux/fsi-sbefifo.h>
 #include <linux/idr.h>
 #include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -87,6 +91,7 @@ struct sbefifo_client {
 	struct list_head xfrs;
 	struct sbefifo *dev;
 	struct kref kref;
+	unsigned long f_flags;
 };
 
 static struct list_head sbefifo_fifos;
@@ -514,6 +519,7 @@ static int sbefifo_open(struct inode *inode, struct file *file)
 		return -ENOMEM;
 
 	file->private_data = client;
+	client->f_flags = file->f_flags;
 
 	return 0;
 }
@@ -538,19 +544,18 @@ static unsigned int sbefifo_poll(struct file *file, poll_table *wait)
 	return mask;
 }
 
-static ssize_t sbefifo_read(struct file *file, char __user *buf, size_t len,
-			    loff_t *offset)
+static ssize_t sbefifo_read_common(struct sbefifo_client *client,
+				   char __user *ubuf, char *kbuf, size_t len)
 {
-	struct sbefifo_client *client = file->private_data;
 	struct sbefifo *sbefifo = client->dev;
 	struct sbefifo_xfr *xfr;
-	ssize_t ret = 0;
 	size_t n;
+	ssize_t ret = 0;
 
 	if ((len >> 2) << 2 != len)
 		return -EINVAL;
 
-	if ((file->f_flags & O_NONBLOCK) && !sbefifo_xfr_rsp_pending(client))
+	if ((client->f_flags & O_NONBLOCK) && !sbefifo_xfr_rsp_pending(client))
 		return -EAGAIN;
 
 	sbefifo_get_client(client);
@@ -569,10 +574,13 @@ static ssize_t sbefifo_read(struct file *file, char __user *buf, size_t len,
 
 	n = min_t(size_t, n, len);
 
-	if (copy_to_user(buf, READ_ONCE(client->rbuf.rpos), n)) {
-		sbefifo_put_client(client);
-		return -EFAULT;
-	}
+	if (ubuf) {
+		if (copy_to_user(ubuf, READ_ONCE(client->rbuf.rpos), n)) {
+			sbefifo_put_client(client);
+			return -EFAULT;
+		}
+	} else
+		memcpy(kbuf, READ_ONCE(client->rbuf.rpos), n);
 
 	if (sbefifo_buf_readnb(&client->rbuf, n)) {
 		xfr = sbefifo_client_next_xfr(client);
@@ -595,10 +603,18 @@ static ssize_t sbefifo_read(struct file *file, char __user *buf, size_t len,
 	return n;
 }
 
-static ssize_t sbefifo_write(struct file *file, const char __user *buf,
-			     size_t len, loff_t *offset)
+static ssize_t sbefifo_read(struct file *file, char __user *buf, size_t len,
+			    loff_t *offset)
 {
 	struct sbefifo_client *client = file->private_data;
+
+	return sbefifo_read_common(client, buf, NULL, len);
+}
+
+static ssize_t sbefifo_write_common(struct sbefifo_client *client,
+				    const char __user *ubuf, const char *kbuf,
+				    size_t len)
+{
 	struct sbefifo *sbefifo = client->dev;
 	struct sbefifo_buf *wbuf = &client->wbuf;
 	struct sbefifo_xfr *xfr;
@@ -616,7 +632,7 @@ static ssize_t sbefifo_write(struct file *file, const char __user *buf,
 	spin_lock_irq(&sbefifo->lock);
 	xfr = sbefifo_next_xfr(sbefifo);
 
-	if ((file->f_flags & O_NONBLOCK) && xfr && n < len) {
+	if ((client->f_flags & O_NONBLOCK) && xfr && n < len) {
 		spin_unlock_irq(&sbefifo->lock);
 		return -EAGAIN;
 	}
@@ -655,18 +671,24 @@ static ssize_t sbefifo_write(struct file *file, const char __user *buf,
 
 		n = min_t(size_t, n, len);
 
-		if (copy_from_user(READ_ONCE(wbuf->wpos), buf, n)) {
-			set_bit(SBEFIFO_XFR_CANCEL, &xfr->flags);
-			sbefifo_get(sbefifo);
-			if (mod_timer(&sbefifo->poll_timer, jiffies))
-				sbefifo_put(sbefifo);
-			sbefifo_put_client(client);
-			return -EFAULT;
+		if (ubuf) {
+			if (copy_from_user(READ_ONCE(wbuf->wpos), ubuf, n)) {
+				set_bit(SBEFIFO_XFR_CANCEL, &xfr->flags);
+				sbefifo_get(sbefifo);
+				if (mod_timer(&sbefifo->poll_timer, jiffies))
+					sbefifo_put(sbefifo);
+				sbefifo_put_client(client);
+				return -EFAULT;
+			}
+
+			ubuf += n;
+		} else {
+			memcpy(READ_ONCE(wbuf->wpos), kbuf, n);
+			kbuf += n;
 		}
 
 		sbefifo_buf_wrotenb(wbuf, n);
 		len -= n;
-		buf += n;
 		ret += n;
 
 		/* Set this before starting timer to avoid race condition on
@@ -688,6 +710,14 @@ static ssize_t sbefifo_write(struct file *file, const char __user *buf,
 	return ret;
 }
 
+static ssize_t sbefifo_write(struct file *file, const char __user *buf,
+			     size_t len, loff_t *offset)
+{
+	struct sbefifo_client *client = file->private_data;
+
+	return sbefifo_write_common(client, buf, NULL, len);
+}
+
 static int sbefifo_release(struct inode *inode, struct file *file)
 {
 	struct sbefifo_client *client = file->private_data;
@@ -707,12 +737,68 @@ static int sbefifo_release(struct inode *inode, struct file *file)
 	.release	= sbefifo_release,
 };
 
+struct sbefifo_client *sbefifo_drv_open(struct device *dev,
+					unsigned long flags)
+{
+	struct sbefifo_client *client = NULL;
+	struct sbefifo *sbefifo;
+	struct fsi_device *fsi_dev = to_fsi_dev(dev);
+
+	list_for_each_entry(sbefifo, &sbefifo_fifos, link) {
+		if (sbefifo->fsi_dev != fsi_dev)
+			continue;
+
+		client = sbefifo_new_client(sbefifo);
+		if (client)
+			client->f_flags = flags;
+	}
+
+	return client;
+}
+EXPORT_SYMBOL_GPL(sbefifo_drv_open);
+
+int sbefifo_drv_read(struct sbefifo_client *client, char *buf, size_t len)
+{
+	return sbefifo_read_common(client, NULL, buf, len);
+}
+EXPORT_SYMBOL_GPL(sbefifo_drv_read);
+
+int sbefifo_drv_write(struct sbefifo_client *client, const char *buf,
+		      size_t len)
+{
+	return sbefifo_write_common(client, NULL, buf, len);
+}
+EXPORT_SYMBOL_GPL(sbefifo_drv_write);
+
+void sbefifo_drv_release(struct sbefifo_client *client)
+{
+	if (!client)
+		return;
+
+	sbefifo_put_client(client);
+}
+EXPORT_SYMBOL_GPL(sbefifo_drv_release);
+
+static int sbefifo_unregister_child(struct device *dev, void *data)
+{
+	struct platform_device *child = to_platform_device(dev);
+
+	of_device_unregister(child);
+	if (dev->of_node)
+		of_node_clear_flag(dev->of_node, OF_POPULATED);
+
+	return 0;
+}
+
 static int sbefifo_probe(struct device *dev)
 {
 	struct fsi_device *fsi_dev = to_fsi_dev(dev);
 	struct sbefifo *sbefifo;
+	struct device_node *np;
+	struct platform_device *child;
+	char child_name[32];
 	u32 sts;
-	int ret;
+	int ret, child_idx = 0;
 
 	sbefifo = kzalloc(sizeof(*sbefifo), GFP_KERNEL);
 	if (!sbefifo)
@@ -759,6 +845,18 @@ static int sbefifo_probe(struct device *dev)
 
 	list_add(&sbefifo->link, &sbefifo_fifos);
 
+	if (dev->of_node) {
+		/* create platform devs for dts child nodes (occ, etc) */
+		for_each_child_of_node(dev->of_node, np) {
+			snprintf(child_name, sizeof(child_name), "%s-dev%d",
+				 sbefifo->name, child_idx++);
+			child = of_platform_device_create(np, child_name, dev);
+			if (!child)
+				dev_warn(&sbefifo->fsi_dev->dev,
+					 "failed to create child node dev\n");
+		}
+	}
+
 	return misc_register(&sbefifo->mdev);
 }
 
@@ -772,6 +870,8 @@ static int sbefifo_remove(struct device *dev)
 		if (sbefifo->fsi_dev != fsi_dev)
 			continue;
 
+		device_for_each_child(dev, NULL, sbefifo_unregister_child);
+
 		misc_deregister(&sbefifo->mdev);
 		list_del(&sbefifo->link);
 		ida_simple_remove(&sbefifo_ida, sbefifo->idx);
diff --git a/include/linux/fsi-sbefifo.h b/include/linux/fsi-sbefifo.h
new file mode 100644
index 0000000..8e55891
--- /dev/null
+++ b/include/linux/fsi-sbefifo.h
@@ -0,0 +1,30 @@
+/*
+ * SBEFIFO FSI Client device driver
+ *
+ * Copyright (C) IBM Corporation 2017
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERGCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef LINUX_FSI_SBEFIFO_H
+#define LINUX_FSI_SBEFIFO_H
+
+struct device;
+struct sbefifo_client;
+
+extern struct sbefifo_client *sbefifo_drv_open(struct device *dev,
+					       unsigned long flags);
+extern int sbefifo_drv_read(struct sbefifo_client *client, char *buf,
+			    size_t len);
+extern int sbefifo_drv_write(struct sbefifo_client *client, const char *buf,
+			     size_t len);
+extern void sbefifo_drv_release(struct sbefifo_client *client);
+
+#endif /* LINUX_FSI_SBEFIFO_H */
-- 
1.8.3.1

[toc] | [prev] | [next] | [standalone]


#1685927 — Re: [PATCH v2 2/5] drivers/fsi/sbefifo: Add in-kernel API

Fromkbuild test robot <lkp@intel.com>
Date2017-07-12 19:30 +0200
SubjectRe: [PATCH v2 2/5] drivers/fsi/sbefifo: Add in-kernel API
Message-ID<u2tCy-2IA-11@gated-at.bofh.it>
In reply to#1681869

[Multipart message — attachments visible in raw view] — view raw

Hi Edward,

[auto build test ERROR on linus/master]
[also build test ERROR on next-20170712]
[cannot apply to v4.12]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Eddie-James/drivers-fsi-Add-SBEFIFO-and-OCC-drivers/20170707-232144
config: um-allyesconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=um 

All errors (new ones prefixed by >>):

   arch/um/drivers/built-in.o: In function `vde_open_real':
   (.text+0xc9f1): warning: Using 'getgrnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/built-in.o: In function `vde_open_real':
   (.text+0xc83c): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/built-in.o: In function `vde_open_real':
   (.text+0xcb55): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/built-in.o: In function `pcap_nametoaddr':
   (.text+0x1d5e5): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/built-in.o: In function `pcap_nametonetaddr':
   (.text+0x1d685): warning: Using 'getnetbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/built-in.o: In function `pcap_nametoproto':
   (.text+0x1d8a5): warning: Using 'getprotobyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/built-in.o: In function `pcap_nametoport':
   (.text+0x1d6d7): warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   drivers/built-in.o: In function `img_ascii_lcd_probe':
   drivers/auxdisplay/img-ascii-lcd.c:386: undefined reference to `devm_ioremap_resource'
   drivers/built-in.o: In function `sbefifo_probe':
>> drivers/fsi/fsi-sbefifo.c:853: undefined reference to `of_platform_device_create'
   collect2: error: ld returned 1 exit status

vim +853 drivers/fsi/fsi-sbefifo.c

   792	
   793	static int sbefifo_probe(struct device *dev)
   794	{
   795		struct fsi_device *fsi_dev = to_fsi_dev(dev);
   796		struct sbefifo *sbefifo;
   797		struct device_node *np;
   798		struct platform_device *child;
   799		char child_name[32];
   800		u32 sts;
   801		int ret, child_idx = 0;
   802	
   803		sbefifo = kzalloc(sizeof(*sbefifo), GFP_KERNEL);
   804		if (!sbefifo)
   805			return -ENOMEM;
   806	
   807		sbefifo->fsi_dev = fsi_dev;
   808	
   809		ret = sbefifo_inw(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &sts);
   810		if (ret)
   811			return ret;
   812	
   813		if (!(sts & SBEFIFO_EMPTY)) {
   814			dev_err(&sbefifo->fsi_dev->dev,
   815				"Found data in upstream fifo\n");
   816			return -EIO;
   817		}
   818	
   819		ret = sbefifo_inw(sbefifo, SBEFIFO_DWN | SBEFIFO_STS, &sts);
   820		if (ret)
   821			return ret;
   822	
   823		if (!(sts & SBEFIFO_EMPTY)) {
   824			dev_err(&sbefifo->fsi_dev->dev,
   825				"Found data in downstream fifo\n");
   826			return -EIO;
   827		}
   828	
   829		sbefifo->mdev.minor = MISC_DYNAMIC_MINOR;
   830		sbefifo->mdev.fops = &sbefifo_fops;
   831		sbefifo->mdev.name = sbefifo->name;
   832		sbefifo->mdev.parent = dev;
   833		spin_lock_init(&sbefifo->lock);
   834		kref_init(&sbefifo->kref);
   835	
   836		sbefifo->idx = ida_simple_get(&sbefifo_ida, 1, INT_MAX, GFP_KERNEL);
   837		snprintf(sbefifo->name, sizeof(sbefifo->name), "sbefifo%d",
   838			 sbefifo->idx);
   839		init_waitqueue_head(&sbefifo->wait);
   840		INIT_LIST_HEAD(&sbefifo->xfrs);
   841	
   842		/* This bit of silicon doesn't offer any interrupts... */
   843		setup_timer(&sbefifo->poll_timer, sbefifo_poll_timer,
   844			    (unsigned long)sbefifo);
   845	
   846		list_add(&sbefifo->link, &sbefifo_fifos);
   847	
   848		if (dev->of_node) {
   849			/* create platform devs for dts child nodes (occ, etc) */
   850			for_each_child_of_node(dev->of_node, np) {
   851				snprintf(child_name, sizeof(child_name), "%s-dev%d",
   852					 sbefifo->name, child_idx++);
 > 853				child = of_platform_device_create(np, child_name, dev);
   854				if (!child)
   855					dev_warn(&sbefifo->fsi_dev->dev,
   856						 "failed to create child node dev\n");
   857			}
   858		}
   859	
   860		return misc_register(&sbefifo->mdev);
   861	}
   862	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web