tb.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Thunderbolt Cactus Ridge driver - bus logic (NHI independent)
  3. *
  4. * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
  5. */
  6. #ifndef TB_H_
  7. #define TB_H_
  8. #include <linux/pci.h>
  9. #include "tb_regs.h"
  10. #include "ctl.h"
  11. /**
  12. * struct tb_switch - a thunderbolt switch
  13. */
  14. struct tb_switch {
  15. struct tb_regs_switch_header config;
  16. struct tb_port *ports;
  17. struct tb *tb;
  18. u64 uid;
  19. int cap_plug_events; /* offset, zero if not found */
  20. bool is_unplugged; /* unplugged, will go away */
  21. u8 *drom;
  22. };
  23. /**
  24. * struct tb_port - a thunderbolt port, part of a tb_switch
  25. */
  26. struct tb_port {
  27. struct tb_regs_port_header config;
  28. struct tb_switch *sw;
  29. struct tb_port *remote; /* remote port, NULL if not connected */
  30. int cap_phy; /* offset, zero if not found */
  31. u8 port; /* port number on switch */
  32. bool disabled; /* disabled by eeprom */
  33. struct tb_port *dual_link_port;
  34. u8 link_nr:1;
  35. };
  36. /**
  37. * struct tb_path_hop - routing information for a tb_path
  38. *
  39. * Hop configuration is always done on the IN port of a switch.
  40. * in_port and out_port have to be on the same switch. Packets arriving on
  41. * in_port with "hop" = in_hop_index will get routed to through out_port. The
  42. * next hop to take (on out_port->remote) is determined by next_hop_index.
  43. *
  44. * in_counter_index is the index of a counter (in TB_CFG_COUNTERS) on the in
  45. * port.
  46. */
  47. struct tb_path_hop {
  48. struct tb_port *in_port;
  49. struct tb_port *out_port;
  50. int in_hop_index;
  51. int in_counter_index; /* write -1 to disable counters for this hop. */
  52. int next_hop_index;
  53. };
  54. /**
  55. * enum tb_path_port - path options mask
  56. */
  57. enum tb_path_port {
  58. TB_PATH_NONE = 0,
  59. TB_PATH_SOURCE = 1, /* activate on the first hop (out of src) */
  60. TB_PATH_INTERNAL = 2, /* activate on other hops (not the first/last) */
  61. TB_PATH_DESTINATION = 4, /* activate on the last hop (into dst) */
  62. TB_PATH_ALL = 7,
  63. };
  64. /**
  65. * struct tb_path - a unidirectional path between two ports
  66. *
  67. * A path consists of a number of hops (see tb_path_hop). To establish a PCIe
  68. * tunnel two paths have to be created between the two PCIe ports.
  69. *
  70. */
  71. struct tb_path {
  72. struct tb *tb;
  73. int nfc_credits; /* non flow controlled credits */
  74. enum tb_path_port ingress_shared_buffer;
  75. enum tb_path_port egress_shared_buffer;
  76. enum tb_path_port ingress_fc_enable;
  77. enum tb_path_port egress_fc_enable;
  78. int priority:3;
  79. int weight:4;
  80. bool drop_packages;
  81. bool activated;
  82. struct tb_path_hop *hops;
  83. int path_length; /* number of hops */
  84. };
  85. /**
  86. * struct tb - main thunderbolt bus structure
  87. */
  88. struct tb {
  89. struct mutex lock; /*
  90. * Big lock. Must be held when accessing cfg or
  91. * any struct tb_switch / struct tb_port.
  92. */
  93. struct tb_nhi *nhi;
  94. struct tb_ctl *ctl;
  95. struct workqueue_struct *wq; /* ordered workqueue for plug events */
  96. struct tb_switch *root_switch;
  97. struct list_head tunnel_list; /* list of active PCIe tunnels */
  98. bool hotplug_active; /*
  99. * tb_handle_hotplug will stop progressing plug
  100. * events and exit if this is not set (it needs to
  101. * acquire the lock one more time). Used to drain
  102. * wq after cfg has been paused.
  103. */
  104. };
  105. /* helper functions & macros */
  106. /**
  107. * tb_upstream_port() - return the upstream port of a switch
  108. *
  109. * Every switch has an upstream port (for the root switch it is the NHI).
  110. *
  111. * During switch alloc/init tb_upstream_port()->remote may be NULL, even for
  112. * non root switches (on the NHI port remote is always NULL).
  113. *
  114. * Return: Returns the upstream port of the switch.
  115. */
  116. static inline struct tb_port *tb_upstream_port(struct tb_switch *sw)
  117. {
  118. return &sw->ports[sw->config.upstream_port_number];
  119. }
  120. static inline u64 tb_route(struct tb_switch *sw)
  121. {
  122. return ((u64) sw->config.route_hi) << 32 | sw->config.route_lo;
  123. }
  124. static inline int tb_sw_read(struct tb_switch *sw, void *buffer,
  125. enum tb_cfg_space space, u32 offset, u32 length)
  126. {
  127. return tb_cfg_read(sw->tb->ctl,
  128. buffer,
  129. tb_route(sw),
  130. 0,
  131. space,
  132. offset,
  133. length);
  134. }
  135. static inline int tb_sw_write(struct tb_switch *sw, void *buffer,
  136. enum tb_cfg_space space, u32 offset, u32 length)
  137. {
  138. return tb_cfg_write(sw->tb->ctl,
  139. buffer,
  140. tb_route(sw),
  141. 0,
  142. space,
  143. offset,
  144. length);
  145. }
  146. static inline int tb_port_read(struct tb_port *port, void *buffer,
  147. enum tb_cfg_space space, u32 offset, u32 length)
  148. {
  149. return tb_cfg_read(port->sw->tb->ctl,
  150. buffer,
  151. tb_route(port->sw),
  152. port->port,
  153. space,
  154. offset,
  155. length);
  156. }
  157. static inline int tb_port_write(struct tb_port *port, void *buffer,
  158. enum tb_cfg_space space, u32 offset, u32 length)
  159. {
  160. return tb_cfg_write(port->sw->tb->ctl,
  161. buffer,
  162. tb_route(port->sw),
  163. port->port,
  164. space,
  165. offset,
  166. length);
  167. }
  168. #define tb_err(tb, fmt, arg...) dev_err(&(tb)->nhi->pdev->dev, fmt, ## arg)
  169. #define tb_WARN(tb, fmt, arg...) dev_WARN(&(tb)->nhi->pdev->dev, fmt, ## arg)
  170. #define tb_warn(tb, fmt, arg...) dev_warn(&(tb)->nhi->pdev->dev, fmt, ## arg)
  171. #define tb_info(tb, fmt, arg...) dev_info(&(tb)->nhi->pdev->dev, fmt, ## arg)
  172. #define __TB_SW_PRINT(level, sw, fmt, arg...) \
  173. do { \
  174. struct tb_switch *__sw = (sw); \
  175. level(__sw->tb, "%llx: " fmt, \
  176. tb_route(__sw), ## arg); \
  177. } while (0)
  178. #define tb_sw_WARN(sw, fmt, arg...) __TB_SW_PRINT(tb_WARN, sw, fmt, ##arg)
  179. #define tb_sw_warn(sw, fmt, arg...) __TB_SW_PRINT(tb_warn, sw, fmt, ##arg)
  180. #define tb_sw_info(sw, fmt, arg...) __TB_SW_PRINT(tb_info, sw, fmt, ##arg)
  181. #define __TB_PORT_PRINT(level, _port, fmt, arg...) \
  182. do { \
  183. struct tb_port *__port = (_port); \
  184. level(__port->sw->tb, "%llx:%x: " fmt, \
  185. tb_route(__port->sw), __port->port, ## arg); \
  186. } while (0)
  187. #define tb_port_WARN(port, fmt, arg...) \
  188. __TB_PORT_PRINT(tb_WARN, port, fmt, ##arg)
  189. #define tb_port_warn(port, fmt, arg...) \
  190. __TB_PORT_PRINT(tb_warn, port, fmt, ##arg)
  191. #define tb_port_info(port, fmt, arg...) \
  192. __TB_PORT_PRINT(tb_info, port, fmt, ##arg)
  193. struct tb *thunderbolt_alloc_and_start(struct tb_nhi *nhi);
  194. void thunderbolt_shutdown_and_free(struct tb *tb);
  195. void thunderbolt_suspend(struct tb *tb);
  196. void thunderbolt_resume(struct tb *tb);
  197. struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route);
  198. void tb_switch_free(struct tb_switch *sw);
  199. void tb_switch_suspend(struct tb_switch *sw);
  200. int tb_switch_resume(struct tb_switch *sw);
  201. int tb_switch_reset(struct tb *tb, u64 route);
  202. void tb_sw_set_unplugged(struct tb_switch *sw);
  203. struct tb_switch *get_switch_at_route(struct tb_switch *sw, u64 route);
  204. int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
  205. int tb_port_add_nfc_credits(struct tb_port *port, int credits);
  206. int tb_port_clear_counter(struct tb_port *port, int counter);
  207. int tb_find_cap(struct tb_port *port, enum tb_cfg_space space, enum tb_cap cap);
  208. struct tb_path *tb_path_alloc(struct tb *tb, int num_hops);
  209. void tb_path_free(struct tb_path *path);
  210. int tb_path_activate(struct tb_path *path);
  211. void tb_path_deactivate(struct tb_path *path);
  212. bool tb_path_is_invalid(struct tb_path *path);
  213. int tb_drom_read(struct tb_switch *sw);
  214. int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid);
  215. static inline int tb_route_length(u64 route)
  216. {
  217. return (fls64(route) + TB_ROUTE_SHIFT - 1) / TB_ROUTE_SHIFT;
  218. }
  219. static inline bool tb_is_upstream_port(struct tb_port *port)
  220. {
  221. return port == tb_upstream_port(port->sw);
  222. }
  223. /**
  224. * tb_downstream_route() - get route to downstream switch
  225. *
  226. * Port must not be the upstream port (otherwise a loop is created).
  227. *
  228. * Return: Returns a route to the switch behind @port.
  229. */
  230. static inline u64 tb_downstream_route(struct tb_port *port)
  231. {
  232. return tb_route(port->sw)
  233. | ((u64) port->port << (port->sw->config.depth * 8));
  234. }
  235. #endif