diff options
author | Andreas Noever <andreas.noever@gmail.com> | 2014-06-03 22:04:05 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-06-19 23:07:47 +0200 |
commit | 9da672a42878c58af5c50d7389dbae17bea9df38 (patch) | |
tree | d85b6d930f13d03b6ec0c718da7b834dd5221e4a /drivers/thunderbolt/tb.c | |
parent | thunderbolt: Enable plug events (diff) | |
download | linux-9da672a42878c58af5c50d7389dbae17bea9df38.tar.xz linux-9da672a42878c58af5c50d7389dbae17bea9df38.zip |
thunderbolt: Scan for downstream switches
Add utility methods tb_port_state and tb_wait_for_port. Add
tb_scan_switch which recursively checks for downstream switches.
Signed-off-by: Andreas Noever <andreas.noever@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt/tb.c')
-rw-r--r-- | drivers/thunderbolt/tb.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index f1b6100b6cf0..3b716fd123f6 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -11,6 +11,47 @@ #include "tb.h" #include "tb_regs.h" + +/* enumeration & hot plug handling */ + + +static void tb_scan_port(struct tb_port *port); + +/** + * tb_scan_switch() - scan for and initialize downstream switches + */ +static void tb_scan_switch(struct tb_switch *sw) +{ + int i; + for (i = 1; i <= sw->config.max_port_number; i++) + tb_scan_port(&sw->ports[i]); +} + +/** + * tb_scan_port() - check for and initialize switches below port + */ +static void tb_scan_port(struct tb_port *port) +{ + struct tb_switch *sw; + if (tb_is_upstream_port(port)) + return; + if (port->config.type != TB_TYPE_PORT) + return; + if (tb_wait_for_port(port, false) <= 0) + return; + if (port->remote) { + tb_port_WARN(port, "port already has a remote!\n"); + return; + } + sw = tb_switch_alloc(port->sw->tb, tb_downstream_route(port)); + if (!sw) + return; + port->remote = tb_upstream_port(sw); + tb_upstream_port(sw)->remote = port; + tb_scan_switch(sw); +} + + /* hotplug handling */ struct tb_hotplug_event { @@ -134,6 +175,9 @@ struct tb *thunderbolt_alloc_and_start(struct tb_nhi *nhi) if (!tb->root_switch) goto err_locked; + /* Full scan to discover devices added before the driver was loaded. */ + tb_scan_switch(tb->root_switch); + /* Allow tb_handle_hotplug to progress events */ tb->hotplug_active = true; mutex_unlock(&tb->lock); |