thunderbolt: Handle hotplug events
[linux-2.6-block.git] / drivers / thunderbolt / tb.h
1 /*
2  * Thunderbolt Cactus Ridge driver - bus logic (NHI independent)
3  *
4  * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
5  */
6
7 #ifndef TB_H_
8 #define TB_H_
9
10 #include <linux/pci.h>
11
12 #include "tb_regs.h"
13 #include "ctl.h"
14
15 /**
16  * struct tb_switch - a thunderbolt switch
17  */
18 struct tb_switch {
19         struct tb_regs_switch_header config;
20         struct tb_port *ports;
21         struct tb *tb;
22         int cap_plug_events; /* offset, zero if not found */
23         bool is_unplugged; /* unplugged, will go away */
24 };
25
26 /**
27  * struct tb_port - a thunderbolt port, part of a tb_switch
28  */
29 struct tb_port {
30         struct tb_regs_port_header config;
31         struct tb_switch *sw;
32         struct tb_port *remote; /* remote port, NULL if not connected */
33         int cap_phy; /* offset, zero if not found */
34         u8 port; /* port number on switch */
35 };
36
37 /**
38  * struct tb - main thunderbolt bus structure
39  */
40 struct tb {
41         struct mutex lock;      /*
42                                  * Big lock. Must be held when accessing cfg or
43                                  * any struct tb_switch / struct tb_port.
44                                  */
45         struct tb_nhi *nhi;
46         struct tb_ctl *ctl;
47         struct workqueue_struct *wq; /* ordered workqueue for plug events */
48         struct tb_switch *root_switch;
49         bool hotplug_active; /*
50                               * tb_handle_hotplug will stop progressing plug
51                               * events and exit if this is not set (it needs to
52                               * acquire the lock one more time). Used to drain
53                               * wq after cfg has been paused.
54                               */
55
56 };
57
58 /* helper functions & macros */
59
60 /**
61  * tb_upstream_port() - return the upstream port of a switch
62  *
63  * Every switch has an upstream port (for the root switch it is the NHI).
64  *
65  * During switch alloc/init tb_upstream_port()->remote may be NULL, even for
66  * non root switches (on the NHI port remote is always NULL).
67  *
68  * Return: Returns the upstream port of the switch.
69  */
70 static inline struct tb_port *tb_upstream_port(struct tb_switch *sw)
71 {
72         return &sw->ports[sw->config.upstream_port_number];
73 }
74
75 static inline u64 tb_route(struct tb_switch *sw)
76 {
77         return ((u64) sw->config.route_hi) << 32 | sw->config.route_lo;
78 }
79
80 static inline int tb_sw_read(struct tb_switch *sw, void *buffer,
81                              enum tb_cfg_space space, u32 offset, u32 length)
82 {
83         return tb_cfg_read(sw->tb->ctl,
84                            buffer,
85                            tb_route(sw),
86                            0,
87                            space,
88                            offset,
89                            length);
90 }
91
92 static inline int tb_sw_write(struct tb_switch *sw, void *buffer,
93                               enum tb_cfg_space space, u32 offset, u32 length)
94 {
95         return tb_cfg_write(sw->tb->ctl,
96                             buffer,
97                             tb_route(sw),
98                             0,
99                             space,
100                             offset,
101                             length);
102 }
103
104 static inline int tb_port_read(struct tb_port *port, void *buffer,
105                                enum tb_cfg_space space, u32 offset, u32 length)
106 {
107         return tb_cfg_read(port->sw->tb->ctl,
108                            buffer,
109                            tb_route(port->sw),
110                            port->port,
111                            space,
112                            offset,
113                            length);
114 }
115
116 static inline int tb_port_write(struct tb_port *port, void *buffer,
117                                 enum tb_cfg_space space, u32 offset, u32 length)
118 {
119         return tb_cfg_write(port->sw->tb->ctl,
120                             buffer,
121                             tb_route(port->sw),
122                             port->port,
123                             space,
124                             offset,
125                             length);
126 }
127
128 #define tb_err(tb, fmt, arg...) dev_err(&(tb)->nhi->pdev->dev, fmt, ## arg)
129 #define tb_WARN(tb, fmt, arg...) dev_WARN(&(tb)->nhi->pdev->dev, fmt, ## arg)
130 #define tb_warn(tb, fmt, arg...) dev_warn(&(tb)->nhi->pdev->dev, fmt, ## arg)
131 #define tb_info(tb, fmt, arg...) dev_info(&(tb)->nhi->pdev->dev, fmt, ## arg)
132
133
134 #define __TB_SW_PRINT(level, sw, fmt, arg...)           \
135         do {                                            \
136                 struct tb_switch *__sw = (sw);          \
137                 level(__sw->tb, "%llx: " fmt,           \
138                       tb_route(__sw), ## arg);          \
139         } while (0)
140 #define tb_sw_WARN(sw, fmt, arg...) __TB_SW_PRINT(tb_WARN, sw, fmt, ##arg)
141 #define tb_sw_warn(sw, fmt, arg...) __TB_SW_PRINT(tb_warn, sw, fmt, ##arg)
142 #define tb_sw_info(sw, fmt, arg...) __TB_SW_PRINT(tb_info, sw, fmt, ##arg)
143
144
145 #define __TB_PORT_PRINT(level, _port, fmt, arg...)                      \
146         do {                                                            \
147                 struct tb_port *__port = (_port);                       \
148                 level(__port->sw->tb, "%llx:%x: " fmt,                  \
149                       tb_route(__port->sw), __port->port, ## arg);      \
150         } while (0)
151 #define tb_port_WARN(port, fmt, arg...) \
152         __TB_PORT_PRINT(tb_WARN, port, fmt, ##arg)
153 #define tb_port_warn(port, fmt, arg...) \
154         __TB_PORT_PRINT(tb_warn, port, fmt, ##arg)
155 #define tb_port_info(port, fmt, arg...) \
156         __TB_PORT_PRINT(tb_info, port, fmt, ##arg)
157
158
159 struct tb *thunderbolt_alloc_and_start(struct tb_nhi *nhi);
160 void thunderbolt_shutdown_and_free(struct tb *tb);
161
162 struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route);
163 void tb_switch_free(struct tb_switch *sw);
164 void tb_sw_set_unpplugged(struct tb_switch *sw);
165 struct tb_switch *get_switch_at_route(struct tb_switch *sw, u64 route);
166
167 int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
168
169 int tb_find_cap(struct tb_port *port, enum tb_cfg_space space, u32 value);
170
171
172 static inline int tb_route_length(u64 route)
173 {
174         return (fls64(route) + TB_ROUTE_SHIFT - 1) / TB_ROUTE_SHIFT;
175 }
176
177 static inline bool tb_is_upstream_port(struct tb_port *port)
178 {
179         return port == tb_upstream_port(port->sw);
180 }
181
182 /**
183  * tb_downstream_route() - get route to downstream switch
184  *
185  * Port must not be the upstream port (otherwise a loop is created).
186  *
187  * Return: Returns a route to the switch behind @port.
188  */
189 static inline u64 tb_downstream_route(struct tb_port *port)
190 {
191         return tb_route(port->sw)
192                | ((u64) port->port << (port->sw->config.depth * 8));
193 }
194
195 #endif