xref: /openbmc/linux/drivers/thunderbolt/tb.c (revision 9da672a4)
1 /*
2  * Thunderbolt Cactus Ridge driver - bus logic (NHI independent)
3  *
4  * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
5  */
6 
7 #include <linux/slab.h>
8 #include <linux/errno.h>
9 #include <linux/delay.h>
10 
11 #include "tb.h"
12 #include "tb_regs.h"
13 
14 
15 /* enumeration & hot plug handling */
16 
17 
18 static void tb_scan_port(struct tb_port *port);
19 
20 /**
21  * tb_scan_switch() - scan for and initialize downstream switches
22  */
23 static void tb_scan_switch(struct tb_switch *sw)
24 {
25 	int i;
26 	for (i = 1; i <= sw->config.max_port_number; i++)
27 		tb_scan_port(&sw->ports[i]);
28 }
29 
30 /**
31  * tb_scan_port() - check for and initialize switches below port
32  */
33 static void tb_scan_port(struct tb_port *port)
34 {
35 	struct tb_switch *sw;
36 	if (tb_is_upstream_port(port))
37 		return;
38 	if (port->config.type != TB_TYPE_PORT)
39 		return;
40 	if (tb_wait_for_port(port, false) <= 0)
41 		return;
42 	if (port->remote) {
43 		tb_port_WARN(port, "port already has a remote!\n");
44 		return;
45 	}
46 	sw = tb_switch_alloc(port->sw->tb, tb_downstream_route(port));
47 	if (!sw)
48 		return;
49 	port->remote = tb_upstream_port(sw);
50 	tb_upstream_port(sw)->remote = port;
51 	tb_scan_switch(sw);
52 }
53 
54 
55 /* hotplug handling */
56 
57 struct tb_hotplug_event {
58 	struct work_struct work;
59 	struct tb *tb;
60 	u64 route;
61 	u8 port;
62 	bool unplug;
63 };
64 
65 /**
66  * tb_handle_hotplug() - handle hotplug event
67  *
68  * Executes on tb->wq.
69  */
70 static void tb_handle_hotplug(struct work_struct *work)
71 {
72 	struct tb_hotplug_event *ev = container_of(work, typeof(*ev), work);
73 	struct tb *tb = ev->tb;
74 	mutex_lock(&tb->lock);
75 	if (!tb->hotplug_active)
76 		goto out; /* during init, suspend or shutdown */
77 
78 	/* do nothing for now */
79 out:
80 	mutex_unlock(&tb->lock);
81 	kfree(ev);
82 }
83 
84 /**
85  * tb_schedule_hotplug_handler() - callback function for the control channel
86  *
87  * Delegates to tb_handle_hotplug.
88  */
89 static void tb_schedule_hotplug_handler(void *data, u64 route, u8 port,
90 					bool unplug)
91 {
92 	struct tb *tb = data;
93 	struct tb_hotplug_event *ev = kmalloc(sizeof(*ev), GFP_KERNEL);
94 	if (!ev)
95 		return;
96 	INIT_WORK(&ev->work, tb_handle_hotplug);
97 	ev->tb = tb;
98 	ev->route = route;
99 	ev->port = port;
100 	ev->unplug = unplug;
101 	queue_work(tb->wq, &ev->work);
102 }
103 
104 /**
105  * thunderbolt_shutdown_and_free() - shutdown everything
106  *
107  * Free all switches and the config channel.
108  *
109  * Used in the error path of thunderbolt_alloc_and_start.
110  */
111 void thunderbolt_shutdown_and_free(struct tb *tb)
112 {
113 	mutex_lock(&tb->lock);
114 
115 	if (tb->root_switch)
116 		tb_switch_free(tb->root_switch);
117 	tb->root_switch = NULL;
118 
119 	if (tb->ctl) {
120 		tb_ctl_stop(tb->ctl);
121 		tb_ctl_free(tb->ctl);
122 	}
123 	tb->ctl = NULL;
124 	tb->hotplug_active = false; /* signal tb_handle_hotplug to quit */
125 
126 	/* allow tb_handle_hotplug to acquire the lock */
127 	mutex_unlock(&tb->lock);
128 	if (tb->wq) {
129 		flush_workqueue(tb->wq);
130 		destroy_workqueue(tb->wq);
131 		tb->wq = NULL;
132 	}
133 	mutex_destroy(&tb->lock);
134 	kfree(tb);
135 }
136 
137 /**
138  * thunderbolt_alloc_and_start() - setup the thunderbolt bus
139  *
140  * Allocates a tb_cfg control channel, initializes the root switch, enables
141  * plug events and activates pci devices.
142  *
143  * Return: Returns NULL on error.
144  */
145 struct tb *thunderbolt_alloc_and_start(struct tb_nhi *nhi)
146 {
147 	struct tb *tb;
148 
149 	BUILD_BUG_ON(sizeof(struct tb_regs_switch_header) != 5 * 4);
150 	BUILD_BUG_ON(sizeof(struct tb_regs_port_header) != 8 * 4);
151 	BUILD_BUG_ON(sizeof(struct tb_regs_hop) != 2 * 4);
152 
153 	tb = kzalloc(sizeof(*tb), GFP_KERNEL);
154 	if (!tb)
155 		return NULL;
156 
157 	tb->nhi = nhi;
158 	mutex_init(&tb->lock);
159 	mutex_lock(&tb->lock);
160 
161 	tb->wq = alloc_ordered_workqueue("thunderbolt", 0);
162 	if (!tb->wq)
163 		goto err_locked;
164 
165 	tb->ctl = tb_ctl_alloc(tb->nhi, tb_schedule_hotplug_handler, tb);
166 	if (!tb->ctl)
167 		goto err_locked;
168 	/*
169 	 * tb_schedule_hotplug_handler may be called as soon as the config
170 	 * channel is started. Thats why we have to hold the lock here.
171 	 */
172 	tb_ctl_start(tb->ctl);
173 
174 	tb->root_switch = tb_switch_alloc(tb, 0);
175 	if (!tb->root_switch)
176 		goto err_locked;
177 
178 	/* Full scan to discover devices added before the driver was loaded. */
179 	tb_scan_switch(tb->root_switch);
180 
181 	/* Allow tb_handle_hotplug to progress events */
182 	tb->hotplug_active = true;
183 	mutex_unlock(&tb->lock);
184 	return tb;
185 
186 err_locked:
187 	mutex_unlock(&tb->lock);
188 	thunderbolt_shutdown_and_free(tb);
189 	return NULL;
190 }
191 
192