All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <gregkh@linuxfoundation.org>
To: Arnd Bergmann <arnd@arndb.de>, linux-kernel@vger.kernel.org
Cc: Johan Hovold <johan@hovoldconsulting.com>,
	Rui Miguel Silva <rmfrfs@gmail.com>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	Sandeep Patil <sspatil@google.com>,
	Matt Porter <mporter@kernel.crashing.org>,
	John Stultz <john.stultz@linaro.org>,
	Rob Herring <robh@kernel.org>,
	Viresh Kumar <viresh.kumar@linaro.org>,
	Alex Elder <elder@linaro.org>, David Lin <dtwlin@google.com>,
	"Bryan O'Donoghue" <pure.logic@nexus-software.ie>,
	Vaibhav Agarwal <vaibhav.agarwal@linaro.org>,
	Mark Greer <mgreer@animalcreek.com>
Subject: [patch 04/32] greybus: host driver framework
Date: Fri, 16 Sep 2016 15:23:03 +0200	[thread overview]
Message-ID: <20160916132303.GB31174@kroah.com> (raw)
In-Reply-To: <20160916064058.GA17821@kroah.com>


This is the Greybus host driver framework files and logic.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/greybus/hd.c |  257 +++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/greybus/hd.h |   90 +++++++++++++++++
 2 files changed, 347 insertions(+)

--- /dev/null
+++ b/drivers/greybus/hd.c
@@ -0,0 +1,257 @@
+/*
+ * Greybus Host Device
+ *
+ * Copyright 2014-2015 Google Inc.
+ * Copyright 2014-2015 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "greybus.h"
+#include "greybus_trace.h"
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create);
+EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release);
+EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add);
+EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del);
+EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_in);
+EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit);
+
+static struct ida gb_hd_bus_id_map;
+
+int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd,
+		 bool async)
+{
+	if (!hd || !hd->driver || !hd->driver->output)
+		return -EINVAL;
+	return hd->driver->output(hd, req, size, cmd, async);
+}
+EXPORT_SYMBOL_GPL(gb_hd_output);
+
+static ssize_t bus_id_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct gb_host_device *hd = to_gb_host_device(dev);
+
+	return sprintf(buf, "%d\n", hd->bus_id);
+}
+static DEVICE_ATTR_RO(bus_id);
+
+static struct attribute *bus_attrs[] = {
+	&dev_attr_bus_id.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(bus);
+
+int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id)
+{
+	struct ida *id_map = &hd->cport_id_map;
+	int ret;
+
+	ret = ida_simple_get(id_map, cport_id, cport_id + 1, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gb_hd_cport_reserve);
+
+void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id)
+{
+	struct ida *id_map = &hd->cport_id_map;
+
+	ida_simple_remove(id_map, cport_id);
+}
+EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved);
+
+/* Locking: Caller guarantees serialisation */
+int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id,
+				unsigned long flags)
+{
+	struct ida *id_map = &hd->cport_id_map;
+	int ida_start, ida_end;
+
+	if (hd->driver->cport_allocate)
+		return hd->driver->cport_allocate(hd, cport_id, flags);
+
+	if (cport_id < 0) {
+		ida_start = 0;
+		ida_end = hd->num_cports;
+	} else if (cport_id < hd->num_cports) {
+		ida_start = cport_id;
+		ida_end = cport_id + 1;
+	} else {
+		dev_err(&hd->dev, "cport %d not available\n", cport_id);
+		return -EINVAL;
+	}
+
+	return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
+}
+
+/* Locking: Caller guarantees serialisation */
+void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id)
+{
+	if (hd->driver->cport_release) {
+		hd->driver->cport_release(hd, cport_id);
+		return;
+	}
+
+	ida_simple_remove(&hd->cport_id_map, cport_id);
+}
+
+static void gb_hd_release(struct device *dev)
+{
+	struct gb_host_device *hd = to_gb_host_device(dev);
+
+	trace_gb_hd_release(hd);
+
+	if (hd->svc)
+		gb_svc_put(hd->svc);
+	ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id);
+	ida_destroy(&hd->cport_id_map);
+	kfree(hd);
+}
+
+struct device_type greybus_hd_type = {
+	.name		= "greybus_host_device",
+	.release	= gb_hd_release,
+};
+
+struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver,
+					struct device *parent,
+					size_t buffer_size_max,
+					size_t num_cports)
+{
+	struct gb_host_device *hd;
+	int ret;
+
+	/*
+	 * Validate that the driver implements all of the callbacks
+	 * so that we don't have to every time we make them.
+	 */
+	if ((!driver->message_send) || (!driver->message_cancel)) {
+		dev_err(parent, "mandatory hd-callbacks missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) {
+		dev_err(parent, "greybus host-device buffers too small\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (num_cports == 0 || num_cports > CPORT_ID_MAX + 1) {
+		dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/*
+	 * Make sure to never allocate messages larger than what the Greybus
+	 * protocol supports.
+	 */
+	if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) {
+		dev_warn(parent, "limiting buffer size to %u\n",
+			 GB_OPERATION_MESSAGE_SIZE_MAX);
+		buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX;
+	}
+
+	hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
+	if (!hd)
+		return ERR_PTR(-ENOMEM);
+
+	ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL);
+	if (ret < 0) {
+		kfree(hd);
+		return ERR_PTR(ret);
+	}
+	hd->bus_id = ret;
+
+	hd->driver = driver;
+	INIT_LIST_HEAD(&hd->modules);
+	INIT_LIST_HEAD(&hd->connections);
+	ida_init(&hd->cport_id_map);
+	hd->buffer_size_max = buffer_size_max;
+	hd->num_cports = num_cports;
+
+	hd->dev.parent = parent;
+	hd->dev.bus = &greybus_bus_type;
+	hd->dev.type = &greybus_hd_type;
+	hd->dev.groups = bus_groups;
+	hd->dev.dma_mask = hd->dev.parent->dma_mask;
+	device_initialize(&hd->dev);
+	dev_set_name(&hd->dev, "greybus%d", hd->bus_id);
+
+	trace_gb_hd_create(hd);
+
+	hd->svc = gb_svc_create(hd);
+	if (!hd->svc) {
+		dev_err(&hd->dev, "failed to create svc\n");
+		put_device(&hd->dev);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return hd;
+}
+EXPORT_SYMBOL_GPL(gb_hd_create);
+
+int gb_hd_add(struct gb_host_device *hd)
+{
+	int ret;
+
+	ret = device_add(&hd->dev);
+	if (ret)
+		return ret;
+
+	ret = gb_svc_add(hd->svc);
+	if (ret) {
+		device_del(&hd->dev);
+		return ret;
+	}
+
+	trace_gb_hd_add(hd);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gb_hd_add);
+
+void gb_hd_del(struct gb_host_device *hd)
+{
+	trace_gb_hd_del(hd);
+
+	/*
+	 * Tear down the svc and flush any on-going hotplug processing before
+	 * removing the remaining interfaces.
+	 */
+	gb_svc_del(hd->svc);
+
+	device_del(&hd->dev);
+}
+EXPORT_SYMBOL_GPL(gb_hd_del);
+
+void gb_hd_shutdown(struct gb_host_device *hd)
+{
+	gb_svc_del(hd->svc);
+}
+EXPORT_SYMBOL_GPL(gb_hd_shutdown);
+
+void gb_hd_put(struct gb_host_device *hd)
+{
+	put_device(&hd->dev);
+}
+EXPORT_SYMBOL_GPL(gb_hd_put);
+
+int __init gb_hd_init(void)
+{
+	ida_init(&gb_hd_bus_id_map);
+
+	return 0;
+}
+
+void gb_hd_exit(void)
+{
+	ida_destroy(&gb_hd_bus_id_map);
+}
--- /dev/null
+++ b/drivers/greybus/hd.h
@@ -0,0 +1,90 @@
+/*
+ * Greybus Host Device
+ *
+ * Copyright 2014-2015 Google Inc.
+ * Copyright 2014-2015 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#ifndef __HD_H
+#define __HD_H
+
+struct gb_host_device;
+struct gb_message;
+
+struct gb_hd_driver {
+	size_t	hd_priv_size;
+
+	int (*cport_allocate)(struct gb_host_device *hd, int cport_id,
+				unsigned long flags);
+	void (*cport_release)(struct gb_host_device *hd, u16 cport_id);
+	int (*cport_enable)(struct gb_host_device *hd, u16 cport_id,
+				unsigned long flags);
+	int (*cport_disable)(struct gb_host_device *hd, u16 cport_id);
+	int (*cport_connected)(struct gb_host_device *hd, u16 cport_id);
+	int (*cport_flush)(struct gb_host_device *hd, u16 cport_id);
+	int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id,
+				u8 phase, unsigned int timeout);
+	int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id,
+				size_t peer_space, unsigned int timeout);
+	int (*cport_clear)(struct gb_host_device *hd, u16 cport_id);
+
+	int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id,
+			struct gb_message *message, gfp_t gfp_mask);
+	void (*message_cancel)(struct gb_message *message);
+	int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id);
+	int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id);
+	int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd,
+		      bool async);
+	int (*timesync_enable)(struct gb_host_device *hd, u8 count,
+			       u64 frame_time, u32 strobe_delay, u32 refclk);
+	int (*timesync_disable)(struct gb_host_device *hd);
+	int (*timesync_authoritative)(struct gb_host_device *hd,
+				      u64 *frame_time);
+	int (*timesync_get_last_event)(struct gb_host_device *hd,
+				       u64 *frame_time);
+};
+
+struct gb_host_device {
+	struct device dev;
+	int bus_id;
+	const struct gb_hd_driver *driver;
+
+	struct list_head modules;
+	struct list_head connections;
+	struct ida cport_id_map;
+
+	/* Number of CPorts supported by the UniPro IP */
+	size_t num_cports;
+
+	/* Host device buffer constraints */
+	size_t buffer_size_max;
+
+	struct gb_svc *svc;
+	/* Private data for the host driver */
+	unsigned long hd_priv[0] __aligned(sizeof(s64));
+};
+#define to_gb_host_device(d) container_of(d, struct gb_host_device, dev)
+
+int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id);
+void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id);
+int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id,
+					unsigned long flags);
+void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id);
+
+struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver,
+					struct device *parent,
+					size_t buffer_size_max,
+					size_t num_cports);
+int gb_hd_add(struct gb_host_device *hd);
+void gb_hd_del(struct gb_host_device *hd);
+void gb_hd_shutdown(struct gb_host_device *hd);
+void gb_hd_put(struct gb_host_device *hd);
+int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd,
+		 bool in_irq);
+
+int gb_hd_init(void);
+void gb_hd_exit(void);
+
+#endif	/* __HD_H */

  parent reply	other threads:[~2016-09-16 13:23 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-14 10:09 [GIT PULL] Greybus driver subsystem for 4.9-rc1 Greg KH
2016-09-14 17:36 ` Mark Rutland
2016-09-14 17:36   ` Mark Rutland
2016-09-14 18:07   ` Greg KH
2016-09-14 18:07     ` Greg KH
2016-09-14 18:29     ` Greg KH
2016-09-14 18:29       ` Greg KH
2016-09-14 19:05       ` Joe Perches
2016-09-14 19:05         ` Joe Perches
2016-09-15  9:35       ` Bryan O'Donoghue
2016-09-15  9:35         ` Bryan O'Donoghue
2016-09-15 10:13         ` Mark Rutland
2016-09-15 10:13           ` Mark Rutland
2016-09-15 10:35           ` Bryan O'Donoghue
2016-09-15 10:35             ` Bryan O'Donoghue
2016-09-15 10:47             ` Bryan O'Donoghue
2016-09-15 10:47               ` Bryan O'Donoghue
2016-09-15 11:20             ` Mark Rutland
2016-09-15 11:20               ` Mark Rutland
2016-09-15 11:48               ` Bryan O'Donoghue
2016-09-15 11:48                 ` Bryan O'Donoghue
2016-09-15 12:46                 ` Mark Rutland
2016-09-15 12:46                   ` Mark Rutland
2016-09-15 15:40                   ` Bryan O'Donoghue
2016-09-15 15:40                     ` Bryan O'Donoghue
2016-09-15 15:47                     ` Mark Rutland
2016-09-15 15:47                       ` Mark Rutland
2016-09-15 16:09                       ` Bryan O'Donoghue
2016-09-15 16:09                         ` Bryan O'Donoghue
2016-09-14 20:07     ` Rob Herring
2016-09-14 20:07       ` Rob Herring
2016-09-15 10:17       ` Greg KH
2016-09-15 10:17         ` Greg KH
2016-09-15 11:02         ` Bryan O'Donoghue
2016-09-15 11:02           ` Bryan O'Donoghue
     [not found] ` <20160915122141.650632149@bubbles.kroah.org>
     [not found]   ` <20160915122234.640367870@bubbles.kroah.org>
2016-09-15 13:16     ` [patch 11/32] greybus: camera driver Laurent Pinchart
2016-09-15 14:45 ` [GIT PULL] Greybus driver subsystem for 4.9-rc1 Mark Brown
2016-09-16  6:05   ` Greg KH
2016-09-16 10:18     ` Mark Brown
2016-09-16 13:22       ` Greg KH
2016-09-16 14:24         ` Greg KH
2016-09-20  6:41           ` Greg KH
2016-09-20  7:12             ` Vaibhav Agarwal
2016-09-16 12:18     ` Arnd Bergmann
2016-09-21 13:02     ` Mark Rutland
2016-09-21 14:13       ` Greg KH
2016-09-16  6:40 ` [patch 00/32] Greybus driver subsystem Greg KH
2016-09-16  6:41   ` [patch 02/32] greybus: interface control logic Greg KH
2016-09-16 13:22   ` [patch 03/32] greybus: operations logic Greg KH
2016-09-16 13:23   ` Greg KH [this message]
2016-09-16 13:23   ` [patch 05/32] greybus: trace.h Greg KH
2016-09-16 13:23   ` [patch 06/32] greybus: svc driver/watchdog Greg KH
2016-09-16 13:23   ` [patch 07/32] greybus: core code Greg KH
2016-09-16 13:24   ` [patch 08/32] greybus: bootrom driver Greg KH
2016-09-16 13:24   ` [patch 09/32] greybus: firmware download class driver Greg KH
2016-09-16 13:24   ` [patch 10/32] greybus: audio driver Greg KH
2016-09-16 13:25   ` [patch 11/32] greybus: camera driver Greg KH
2016-09-16 13:25   ` [patch 12/32] greybus: es2 host driver Greg KH
2016-10-07 13:43     ` Pavel Machek
2016-09-16 14:09   ` [patch 13/32] greybus: HID driver Greg KH
2016-09-16 14:10   ` [patch 14/32] greybus: LED driver Greg KH
2016-10-07 13:36     ` Pavel Machek
2016-10-07 13:41       ` Greg KH
2016-09-16 14:10   ` [patch 15/32] greybus: logging driver Greg KH
2016-09-16 14:10   ` [patch 16/32] greybus: loopback driver Greg KH
2016-09-16 14:10   ` [patch 17/32] greybus: power supply driver Greg KH
2016-10-07 13:49     ` Pavel Machek
2016-10-07 14:12       ` Greg KH
2016-10-07 18:15         ` Pavel Machek
2016-09-16 14:11   ` [patch 18/32] greybus: raw driver Greg KH
2016-09-16 14:11   ` [patch 19/32] greybus: timesync driver Greg KH
2016-09-16 14:11   ` [patch 20/32] greybus: vibrator driver Greg KH
2016-09-16 14:19   ` [patch 21/32] greybus: arche platform driver Greg KH
2016-09-16 14:20   ` [patch 22/32] greybus: bridged phy bus code Greg KH
2016-09-16 14:20   ` [patch 23/32] greybus: bridged phy gpio driver Greg KH
2016-09-16 14:20   ` [patch 24/32] greybus: bridged phy i2c driver Greg KH
2016-09-16 14:20   ` [patch 25/32] greybus: bridged phy pwm driver Greg KH
2016-09-16 14:21   ` [patch 26/32] greybus: bridged phy sdio driver Greg KH
2016-09-16 14:21   ` [patch 27/32] greybus: bridged phy spi driver Greg KH
2016-09-16 14:21   ` [patch 28/32] greybus: bridged phy uart driver Greg KH
2016-09-16 14:21   ` [patch 29/32] greybus: bridged phy usb driver Greg KH
2016-09-16 14:22   ` [patch 30/32] greybus: tools Greg KH
2016-09-16 14:22   ` [patch 31/32] greybus: documentation Greg KH
2016-09-16 14:22   ` [patch 32/32] greybus: add to the build Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160916132303.GB31174@kroah.com \
    --to=gregkh@linuxfoundation.org \
    --cc=arnd@arndb.de \
    --cc=dtwlin@google.com \
    --cc=elder@linaro.org \
    --cc=johan@hovoldconsulting.com \
    --cc=john.stultz@linaro.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mgreer@animalcreek.com \
    --cc=mporter@kernel.crashing.org \
    --cc=pure.logic@nexus-software.ie \
    --cc=rmfrfs@gmail.com \
    --cc=robh@kernel.org \
    --cc=sspatil@google.com \
    --cc=vaibhav.agarwal@linaro.org \
    --cc=viresh.kumar@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.