All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mika Westerberg <mika.westerberg@linux.intel.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Andreas Noever <andreas.noever@gmail.com>,
	Michael Jamet <michael.jamet@intel.com>,
	Yehezkel Bernat <yehezkel.bernat@intel.com>,
	Lukas Wunner <lukas@wunner.de>,
	Amir Levy <amir.jer.levy@intel.com>,
	Andy Lutomirski <luto@kernel.org>,
	Mario.Limonciello@dell.com, Jared.Dominguez@dell.com,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH v2 17/27] thunderbolt: Let the connection manager handle all notifications
Date: Fri, 26 May 2017 19:09:26 +0300	[thread overview]
Message-ID: <20170526160936.54265-18-mika.westerberg@linux.intel.com> (raw)
In-Reply-To: <20170526160936.54265-1-mika.westerberg@linux.intel.com>

Currently the control channel (ctl.c) handles the one supported
notification (PLUG_EVENT) and sends back ACK accordingly. However, we
are going to add support for the internal connection manager (ICM) that
needs to handle a different notifications. So instead of dealing
everything in the control channel, we change the callback to take an
arbitrary thunderbolt packet and convert the native connection manager
to handle the event itself.

In addition we only push replies we know of to the response FIFO.
Everything else is treated as notification (or request) and is expected
to be dealt by the connection manager implementation.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com>
Reviewed-by: Michael Jamet <michael.jamet@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/thunderbolt/ctl.c    | 86 ++++++++++++++++++++++++++++++--------------
 drivers/thunderbolt/ctl.h    |  5 +--
 drivers/thunderbolt/domain.c | 15 +++++++-
 drivers/thunderbolt/tb.c     | 30 ++++++++++++----
 drivers/thunderbolt/tb.h     |  5 +--
 5 files changed, 103 insertions(+), 38 deletions(-)

diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c
index c6633da582b8..5417ed244edc 100644
--- a/drivers/thunderbolt/ctl.c
+++ b/drivers/thunderbolt/ctl.c
@@ -35,7 +35,7 @@ struct tb_ctl {
 	DECLARE_KFIFO(response_fifo, struct ctl_pkg*, 16);
 	struct completion response_ready;
 
-	hotplug_cb callback;
+	event_cb callback;
 	void *callback_data;
 };
 
@@ -52,6 +52,9 @@ struct tb_ctl {
 #define tb_ctl_info(ctl, format, arg...) \
 	dev_info(&(ctl)->nhi->pdev->dev, format, ## arg)
 
+#define tb_ctl_dbg(ctl, format, arg...) \
+	dev_dbg(&(ctl)->nhi->pdev->dev, format, ## arg)
+
 /* utility functions */
 
 static int check_header(struct ctl_pkg *pkg, u32 len, enum tb_cfg_pkg_type type,
@@ -272,24 +275,12 @@ static int tb_ctl_tx(struct tb_ctl *ctl, const void *data, size_t len,
 }
 
 /**
- * tb_ctl_handle_plug_event() - acknowledge a plug event, invoke ctl->callback
+ * tb_ctl_handle_event() - acknowledge a plug event, invoke ctl->callback
  */
-static void tb_ctl_handle_plug_event(struct tb_ctl *ctl,
-				     struct ctl_pkg *response)
+static void tb_ctl_handle_event(struct tb_ctl *ctl, enum tb_cfg_pkg_type type,
+				struct ctl_pkg *pkg, size_t size)
 {
-	struct cfg_event_pkg *pkg = response->buffer;
-	u64 route = tb_cfg_get_route(&pkg->header);
-
-	if (check_header(response, sizeof(*pkg), TB_CFG_PKG_EVENT, route)) {
-		tb_ctl_warn(ctl, "malformed TB_CFG_PKG_EVENT\n");
-		return;
-	}
-
-	if (tb_cfg_error(ctl, route, pkg->port, TB_CFG_ERROR_ACK_PLUG_EVENT))
-		tb_ctl_warn(ctl, "could not ack plug event on %llx:%x\n",
-			    route, pkg->port);
-	WARN(pkg->zero, "pkg->zero is %#x\n", pkg->zero);
-	ctl->callback(ctl->callback_data, route, pkg->port, pkg->unplug);
+	ctl->callback(ctl->callback_data, type, pkg->buffer, size);
 }
 
 static void tb_ctl_rx_submit(struct ctl_pkg *pkg)
@@ -302,10 +293,29 @@ static void tb_ctl_rx_submit(struct ctl_pkg *pkg)
 					     */
 }
 
+static int tb_async_error(const struct ctl_pkg *pkg)
+{
+	const struct cfg_error_pkg *error = (const struct cfg_error_pkg *)pkg;
+
+	if (pkg->frame.eof != TB_CFG_PKG_ERROR)
+		return false;
+
+	switch (error->error) {
+	case TB_CFG_ERROR_LINK_ERROR:
+	case TB_CFG_ERROR_HEC_ERROR_DETECTED:
+	case TB_CFG_ERROR_FLOW_CONTROL_ERROR:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 static void tb_ctl_rx_callback(struct tb_ring *ring, struct ring_frame *frame,
 			       bool canceled)
 {
 	struct ctl_pkg *pkg = container_of(frame, typeof(*pkg), frame);
+	__be32 crc32;
 
 	if (canceled)
 		return; /*
@@ -320,18 +330,42 @@ static void tb_ctl_rx_callback(struct tb_ring *ring, struct ring_frame *frame,
 	}
 
 	frame->size -= 4; /* remove checksum */
-	if (*(__be32 *) (pkg->buffer + frame->size)
-			!= tb_crc(pkg->buffer, frame->size)) {
-		tb_ctl_err(pkg->ctl,
-			   "RX: checksum mismatch, dropping packet\n");
-		goto rx;
-	}
+	crc32 = tb_crc(pkg->buffer, frame->size);
 	be32_to_cpu_array(pkg->buffer, pkg->buffer, frame->size / 4);
 
-	if (frame->eof == TB_CFG_PKG_EVENT) {
-		tb_ctl_handle_plug_event(pkg->ctl, pkg);
+	switch (frame->eof) {
+	case TB_CFG_PKG_READ:
+	case TB_CFG_PKG_WRITE:
+	case TB_CFG_PKG_ERROR:
+	case TB_CFG_PKG_OVERRIDE:
+	case TB_CFG_PKG_RESET:
+		if (*(__be32 *)(pkg->buffer + frame->size) != crc32) {
+			tb_ctl_err(pkg->ctl,
+				   "RX: checksum mismatch, dropping packet\n");
+			goto rx;
+		}
+		if (tb_async_error(pkg)) {
+			tb_ctl_handle_event(pkg->ctl, frame->eof,
+					    pkg, frame->size);
+			goto rx;
+		}
+		break;
+
+	case TB_CFG_PKG_EVENT:
+		if (*(__be32 *)(pkg->buffer + frame->size) != crc32) {
+			tb_ctl_err(pkg->ctl,
+				   "RX: checksum mismatch, dropping packet\n");
+			goto rx;
+		}
+		tb_ctl_handle_event(pkg->ctl, frame->eof, pkg, frame->size);
+		goto rx;
+
+	default:
+		tb_ctl_dbg(pkg->ctl, "RX: unknown package %#x, dropping\n",
+			   frame->eof);
 		goto rx;
 	}
+
 	if (!kfifo_put(&pkg->ctl->response_fifo, pkg)) {
 		tb_ctl_err(pkg->ctl, "RX: fifo is full\n");
 		goto rx;
@@ -379,7 +413,7 @@ static struct tb_cfg_result tb_ctl_rx(struct tb_ctl *ctl, void *buffer,
  *
  * Return: Returns a pointer on success or NULL on failure.
  */
-struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, hotplug_cb cb, void *cb_data)
+struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, event_cb cb, void *cb_data)
 {
 	int i;
 	struct tb_ctl *ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
diff --git a/drivers/thunderbolt/ctl.h b/drivers/thunderbolt/ctl.h
index 914da86ec77d..2b23e030a85b 100644
--- a/drivers/thunderbolt/ctl.h
+++ b/drivers/thunderbolt/ctl.h
@@ -13,9 +13,10 @@
 /* control channel */
 struct tb_ctl;
 
-typedef void (*hotplug_cb)(void *data, u64 route, u8 port, bool unplug);
+typedef void (*event_cb)(void *data, enum tb_cfg_pkg_type type,
+			 const void *buf, size_t size);
 
-struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, hotplug_cb cb, void *cb_data);
+struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, event_cb cb, void *cb_data);
 void tb_ctl_start(struct tb_ctl *ctl);
 void tb_ctl_stop(struct tb_ctl *ctl);
 void tb_ctl_free(struct tb_ctl *ctl);
diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
index e2f3777edee6..8ba6999c3165 100644
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -94,6 +94,19 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, size_t privsize)
 	return NULL;
 }
 
+static void tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type,
+			       const void *buf, size_t size)
+{
+	struct tb *tb = data;
+
+	if (!tb->cm_ops->handle_event) {
+		tb_warn(tb, "domain does not have event handler\n");
+		return;
+	}
+
+	tb->cm_ops->handle_event(tb, type, buf, size);
+}
+
 /**
  * tb_domain_add() - Add domain to the system
  * @tb: Domain to add
@@ -114,7 +127,7 @@ int tb_domain_add(struct tb *tb)
 
 	mutex_lock(&tb->lock);
 
-	tb->ctl = tb_ctl_alloc(tb->nhi, tb->cm_ops->hotplug, tb);
+	tb->ctl = tb_ctl_alloc(tb->nhi, tb_domain_event_cb, tb);
 	if (!tb->ctl) {
 		ret = -ENOMEM;
 		goto err_unlock;
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 94ecac012428..ea9de49b5e10 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -311,18 +311,34 @@ static void tb_handle_hotplug(struct work_struct *work)
  *
  * Delegates to tb_handle_hotplug.
  */
-static void tb_schedule_hotplug_handler(void *data, u64 route, u8 port,
-					bool unplug)
+static void tb_handle_event(struct tb *tb, enum tb_cfg_pkg_type type,
+			    const void *buf, size_t size)
 {
-	struct tb *tb = data;
-	struct tb_hotplug_event *ev = kmalloc(sizeof(*ev), GFP_KERNEL);
+	const struct cfg_event_pkg *pkg = buf;
+	struct tb_hotplug_event *ev;
+	u64 route;
+
+	if (type != TB_CFG_PKG_EVENT) {
+		tb_warn(tb, "unexpected event %#x, ignoring\n", type);
+		return;
+	}
+
+	route = tb_cfg_get_route(&pkg->header);
+
+	if (tb_cfg_error(tb->ctl, route, pkg->port,
+			 TB_CFG_ERROR_ACK_PLUG_EVENT)) {
+		tb_warn(tb, "could not ack plug event on %llx:%x\n", route,
+			pkg->port);
+	}
+
+	ev = kmalloc(sizeof(*ev), GFP_KERNEL);
 	if (!ev)
 		return;
 	INIT_WORK(&ev->work, tb_handle_hotplug);
 	ev->tb = tb;
 	ev->route = route;
-	ev->port = port;
-	ev->unplug = unplug;
+	ev->port = pkg->port;
+	ev->unplug = pkg->unplug;
 	queue_work(tb->wq, &ev->work);
 }
 
@@ -419,7 +435,7 @@ static const struct tb_cm_ops tb_cm_ops = {
 	.stop = tb_stop,
 	.suspend_noirq = tb_suspend_noirq,
 	.resume_noirq = tb_resume_noirq,
-	.hotplug = tb_schedule_hotplug_handler,
+	.handle_event = tb_handle_event,
 };
 
 struct tb *tb_probe(struct tb_nhi *nhi)
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 5e66dce53c65..73db614fa913 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -118,14 +118,15 @@ struct tb_path {
  * @stop: Stops the domain
  * @suspend_noirq: Connection manager specific suspend_noirq
  * @resume_noirq: Connection manager specific resume_noirq
- * @hotplug: Handle hotplug event
+ * @handle_event: Handle thunderbolt event
  */
 struct tb_cm_ops {
 	int (*start)(struct tb *tb);
 	void (*stop)(struct tb *tb);
 	int (*suspend_noirq)(struct tb *tb);
 	int (*resume_noirq)(struct tb *tb);
-	hotplug_cb hotplug;
+	void (*handle_event)(struct tb *tb, enum tb_cfg_pkg_type,
+			     const void *buf, size_t size);
 };
 
 /**
-- 
2.11.0

  parent reply	other threads:[~2017-05-26 16:16 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-26 16:09 [PATCH v2 00/27] Thunderbolt security levels and NVM firmware upgrade Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 01/27] thunderbolt: Use const buffer pointer in write operations Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 02/27] thunderbolt: No need to read UID of the root switch on resume Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 03/27] thunderbolt: Do not try to read UID if DROM offset is read as 0 Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 04/27] thunderbolt: Do not warn about newer DROM versions Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 05/27] thunderbolt: Add MSI-X support Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 06/27] thunderbolt: Rework capability handling Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 07/27] thunderbolt: Allow passing NULL to tb_ctl_free() Mika Westerberg
2017-05-27 15:41   ` Andy Shevchenko
2017-05-28  8:13     ` Mika Westerberg
2017-05-29 12:14       ` Andy Shevchenko
2017-05-26 16:09 ` [PATCH v2 08/27] thunderbolt: Introduce thunderbolt bus and connection manager Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 09/27] thunderbolt: Convert switch to a device Mika Westerberg
2017-05-27 15:45   ` Andy Shevchenko
2017-05-28  8:40     ` Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 10/27] thunderbolt: Fail switch adding operation if reading DROM fails Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 11/27] thunderbolt: Do not fail if DROM data CRC32 is invalid Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 12/27] thunderbolt: Refactor and fix parsing of port drom entries Mika Westerberg
2017-05-27 15:46   ` Andy Shevchenko
2017-05-26 16:09 ` [PATCH v2 13/27] thunderbolt: Read vendor and device name from DROM Mika Westerberg
2017-05-27 15:57   ` Andy Shevchenko
2017-05-27 15:58     ` Andy Shevchenko
2017-05-28  8:45     ` Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 14/27] thunderbolt: Move control channel messages to tb_msgs.h Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 15/27] thunderbolt: Expose get_route() to other files Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 16/27] thunderbolt: Expose make_header() " Mika Westerberg
2017-05-26 16:09 ` Mika Westerberg [this message]
2017-05-26 16:09 ` [PATCH v2 18/27] thunderbolt: Rework control channel to be more reliable Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 19/27] thunderbolt: Add new Thunderbolt PCI IDs Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 20/27] thunderbolt: Add support for NHI mailbox Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 21/27] thunderbolt: Store Thunderbolt generation in the switch structure Mika Westerberg
2017-05-27 16:03   ` Andy Shevchenko
2017-05-26 16:09 ` [PATCH v2 22/27] thunderbolt: Add support for DMA configuration based mailbox Mika Westerberg
2017-05-27 16:08   ` Andy Shevchenko
2017-05-28  9:10     ` Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 23/27] thunderbolt: Do not touch the hardware if the NHI is gone on resume Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 24/27] thunderbolt: Add support for Internal Connection Manager (ICM) Mika Westerberg
2017-05-27 20:45   ` Andy Shevchenko
2017-05-28  9:13     ` Mika Westerberg
2017-05-28 10:13       ` Andy Shevchenko
2017-05-26 16:09 ` [PATCH v2 25/27] thunderbolt: Add support for host and device NVM firmware upgrade Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 26/27] thunderbolt: Add documentation how Thunderbolt bus can be used Mika Westerberg
2017-05-26 16:09 ` [PATCH v2 27/27] MAINTAINERS: Add maintainers for Thunderbolt driver Mika Westerberg

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=20170526160936.54265-18-mika.westerberg@linux.intel.com \
    --to=mika.westerberg@linux.intel.com \
    --cc=Jared.Dominguez@dell.com \
    --cc=Mario.Limonciello@dell.com \
    --cc=amir.jer.levy@intel.com \
    --cc=andreas.noever@gmail.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=luto@kernel.org \
    --cc=michael.jamet@intel.com \
    --cc=yehezkel.bernat@intel.com \
    /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.