lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 29 Nov 2013 02:35:40 +0100
From:	Andreas Noever <andreas.noever@...il.com>
To:	linux-kernel@...r.kernel.org
Cc:	Andreas Noever <andreas.noever@...il.com>
Subject: [PATCH 03/12] thunderbolt: Setup configuration channel

Add struct tb which will contain our view of the thunderbolt bus. For
now it just contains a pointer to the configuration channel and a
workqueue for hotplug events.

Add thunderbolt_alloc_and_start() and thunderbolt_shutdown_and_free()
which are responsible for setup and teardown of struct tb.

Signed-off-by: Andreas Noever <andreas.noever@...il.com>
---
 drivers/thunderbolt/Makefile  |   2 +-
 drivers/thunderbolt/dsl3510.c |  18 +++++-
 drivers/thunderbolt/tb.c      | 124 ++++++++++++++++++++++++++++++++++++++++++
 drivers/thunderbolt/tb.h      |  34 ++++++++++++
 4 files changed, 175 insertions(+), 3 deletions(-)
 create mode 100644 drivers/thunderbolt/tb.c
 create mode 100644 drivers/thunderbolt/tb.h

diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile
index f486295..7c5b811 100644
--- a/drivers/thunderbolt/Makefile
+++ b/drivers/thunderbolt/Makefile
@@ -1,3 +1,3 @@
 obj-${CONFIG_THUNDERBOLT} := thunderbolt.o
-thunderbolt-objs := dsl3510.o tb_cfg.o
+thunderbolt-objs := dsl3510.o tb_cfg.o tb.o
 
diff --git a/drivers/thunderbolt/dsl3510.c b/drivers/thunderbolt/dsl3510.c
index 2a326f6..434812b 100644
--- a/drivers/thunderbolt/dsl3510.c
+++ b/drivers/thunderbolt/dsl3510.c
@@ -12,6 +12,7 @@
 
 #include "dsl3510.h"
 #include "dsl3510_regs.h"
+#include "tb.h"
 
 #define RING_TYPE(ring) ((ring)->is_tx ? "TX ring" : "RX ring")
 
@@ -481,6 +482,7 @@ static void dsl3510_shutdown(struct tb_nhi *nhi)
 static int dsl3510_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct tb_nhi *nhi;
+	struct tb *tb;
 	int res;
 
 	res = pcim_enable_device(pdev);
@@ -543,14 +545,26 @@ static int dsl3510_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* magic value - clock related? */
 	iowrite32(3906250 / 10000, nhi->iobase + 0x38c00);
 
-	pci_set_drvdata(pdev, nhi); /* for dsl3510_remove only */
+	dev_info(&nhi->pdev->dev, "NHI initialized, starting thunderbolt\n");
+	tb = thunderbolt_alloc_and_start(nhi);
+	if (!tb) {
+		/*
+		 * At this point the RX/TX rings might already have been
+		 * activated. Do a proper shutdown.
+		 */
+		dsl3510_shutdown(nhi);
+		return -EIO;
+	}
+	pci_set_drvdata(pdev, tb); /* for dsl3510_remove only */
 
 	return 0;
 }
 
 static void dsl3510_remove(struct pci_dev *pdev)
 {
-	struct tb_nhi *nhi = pci_get_drvdata(pdev);
+	struct tb *tb = pci_get_drvdata(pdev);
+	struct tb_nhi *nhi = tb->nhi;
+	thunderbolt_shutdown_and_free(tb);
 	dsl3510_shutdown(nhi);
 }
 
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
new file mode 100644
index 0000000..64deb7b
--- /dev/null
+++ b/drivers/thunderbolt/tb.c
@@ -0,0 +1,124 @@
+/*
+ * Device independent Thunderbolt bus logic
+ *
+ * Copyright (c) 2013 Andreas Noever <andreas.noever@...il.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include "tb.h"
+
+struct tb_hotplug_event {
+	struct work_struct work;
+	struct tb *tb;
+	u64 route;
+	u8 port;
+	bool unplug;
+};
+
+/**
+ * tb_handle_hotplug() - handle hotplug event
+ *
+ * Executes on the tb->wq.
+ */
+static void tb_handle_hotplug(struct work_struct *work)
+{
+	struct tb_hotplug_event *ev = container_of(work, typeof(*ev), work);
+	struct tb *tb = ev->tb;
+	mutex_lock(&tb->lock);
+	if (tb->shutdown)
+		goto out;
+	/* do nothing for now */
+out:
+	mutex_unlock(&tb->lock);
+	kfree(ev);
+}
+
+/**
+ * tb_schedule_hotplug_handler() - callback function for the config channel
+ *
+ * Delegates to tb_handle_hotplug.
+ */
+static void tb_schedule_hotplug_handler(void *data, u64 route, u8 port,
+					bool unplug)
+{
+	struct tb *tb = data;
+	struct tb_hotplug_event *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;
+	queue_work(tb->wq, &ev->work);
+}
+
+/**
+ * thunderbolt_shutdown_and_free() - shutdown everything
+ *
+ * Free the config channel.
+ */
+void thunderbolt_shutdown_and_free(struct tb *tb)
+{
+	mutex_lock(&tb->lock);
+	tb->shutdown = true; /* signal tb_handle_hotplug to quit */
+
+	if (tb->cfg)
+		tb_cfg_free(tb->cfg);
+	tb->cfg = NULL;
+
+	/* allow tb_handle_hotplug to acquire the lock */
+	mutex_unlock(&tb->lock);
+	if (tb->wq) {
+		flush_workqueue(tb->wq);
+		destroy_workqueue(tb->wq);
+		tb->wq = NULL;
+	}
+	mutex_destroy(&tb->lock);
+	kfree(tb);
+}
+
+/**
+ * thunderbolt_alloc_and_start() - setup the thunderbolt bus
+ *
+ * Allocates a tb_cfg control channel.
+ *
+ * Return: Returns NULL on error.
+ */
+struct tb *thunderbolt_alloc_and_start(struct tb_nhi *nhi)
+{
+	struct tb *tb;
+
+	tb = kzalloc(sizeof(*tb), GFP_KERNEL);
+	if (!tb)
+		return NULL;
+
+	tb->nhi = nhi;
+	mutex_init(&tb->lock);
+	mutex_lock(&tb->lock);
+
+	tb->wq = alloc_ordered_workqueue("thunderbolt", 0);
+	if (!tb->wq)
+		goto err_locked;
+
+	/*
+	 * tb_schedule_hotplug_handler may be called as soon as the config
+	 * channel is allocated. Thats why we have to hold the lock here.
+	 */
+	tb->cfg = tb_cfg_alloc(tb->nhi, tb_schedule_hotplug_handler, tb);
+	if (!tb->cfg)
+		goto err_locked;
+
+	mutex_unlock(&tb->lock);
+	return tb;
+
+err_locked:
+	/* In case tb_handle_hotplug is already executing. */
+	tb->shutdown = true;
+	mutex_unlock(&tb->lock);
+	thunderbolt_shutdown_and_free(tb);
+	return NULL;
+}
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
new file mode 100644
index 0000000..a3378dc
--- /dev/null
+++ b/drivers/thunderbolt/tb.h
@@ -0,0 +1,34 @@
+/*
+ * Device independent Thunderbolt bus logic
+ *
+ * Copyright (c) 2013 Andreas Noever <andreas.noever@...il.com>
+ */
+
+#ifndef TB_H_
+#define TB_H_
+
+#include <linux/pci.h>
+
+#include "tb_cfg.h"
+
+/**
+ * struct tb - main thunderbolt bus structure
+ */
+struct tb {
+	struct mutex lock;	/*
+				 * Big lock. Must be held when accessing cfg or
+				 * any struct tb_switch / struct tb_port.
+				 */
+	struct tb_nhi *nhi;
+	struct tb_cfg *cfg;
+	struct workqueue_struct *wq; /* ordered workqueue for plug events */
+	bool shutdown;	/*
+			 * Once this is set tb_handle_hotplug will exit (once it
+			 * can aquire lock at least once). Used to drain wq.
+			 */
+};
+
+struct tb *thunderbolt_alloc_and_start(struct tb_nhi *nhi);
+void thunderbolt_shutdown_and_free(struct tb *tb);
+
+#endif
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ