Lines Matching full:path
3 * Thunderbolt driver - path/tunnel functionality
50 tb_port_warn(port, "failed to read path at %d\n", hopid); in tb_path_find_dst_port()
81 * tb_path_discover() - Discover a path
82 * @src: First input port of a path
83 * @src_hopid: Starting HopID of a path (%-1 if don't care)
84 * @dst: Expected destination port of the path (%NULL if don't care)
87 * @name: Name of the path
89 * Follows a path starting from @src and @src_hopid to the last output
90 * port of the path. Allocates HopIDs for the visited ports. Call
91 * tb_path_free() to release the path and allocated HopIDs when the path
95 * that the @dst port is the expected one. If it is not, the path can be
98 * Return: Discovered path on success, %NULL in case of failure
106 struct tb_path *path; in tb_path_discover() local
116 * so in that case find a path that ends on @dst with in tb_path_discover()
134 tb_port_warn(p, "failed to read path at %d\n", h); in tb_path_discover()
138 /* If the hop is not enabled we got an incomplete path */ in tb_path_discover()
151 path = kzalloc(sizeof(*path), GFP_KERNEL); in tb_path_discover()
152 if (!path) in tb_path_discover()
155 path->name = name; in tb_path_discover()
156 path->tb = src->sw->tb; in tb_path_discover()
157 path->path_length = num_hops; in tb_path_discover()
158 path->activated = true; in tb_path_discover()
160 path->hops = kcalloc(num_hops, sizeof(*path->hops), GFP_KERNEL); in tb_path_discover()
161 if (!path->hops) { in tb_path_discover()
162 kfree(path); in tb_path_discover()
176 tb_port_warn(p, "failed to read path at %d\n", h); in tb_path_discover()
191 path->hops[i].in_port = p; in tb_path_discover()
192 path->hops[i].in_hop_index = h; in tb_path_discover()
193 path->hops[i].in_counter_index = -1; in tb_path_discover()
194 path->hops[i].out_port = out_port; in tb_path_discover()
195 path->hops[i].next_hop_index = next_hop; in tb_path_discover()
201 return path; in tb_path_discover()
204 tb_port_warn(src, "failed to discover path starting at HopID %d\n", in tb_path_discover()
206 tb_path_free(path); in tb_path_discover()
211 * tb_path_alloc() - allocate a thunderbolt path between two ports
213 * @src: Source port of the path
214 * @src_hopid: HopID used for the first ingress port in the path
215 * @dst: Destination port of the path
216 * @dst_hopid: HopID used for the last egress port in the path
217 * @link_nr: Preferred link if there are dual links on the path
218 * @name: Name of the path
220 * Creates path between two ports starting with given @src_hopid. Reserves
223 * links on the path, prioritizes using @link_nr but takes into account
234 struct tb_path *path; in tb_path_alloc() local
238 path = kzalloc(sizeof(*path), GFP_KERNEL); in tb_path_alloc()
239 if (!path) in tb_path_alloc()
253 kfree(path); in tb_path_alloc()
260 path->hops = kcalloc(num_hops, sizeof(*path->hops), GFP_KERNEL); in tb_path_alloc()
261 if (!path->hops) { in tb_path_alloc()
262 kfree(path); in tb_path_alloc()
320 path->hops[i].in_hop_index = in_hopid; in tb_path_alloc()
321 path->hops[i].in_port = in_port; in tb_path_alloc()
322 path->hops[i].in_counter_index = -1; in tb_path_alloc()
323 path->hops[i].out_port = out_port; in tb_path_alloc()
324 path->hops[i].next_hop_index = out_hopid; in tb_path_alloc()
329 path->tb = tb; in tb_path_alloc()
330 path->path_length = num_hops; in tb_path_alloc()
331 path->name = name; in tb_path_alloc()
333 return path; in tb_path_alloc()
336 tb_path_free(path); in tb_path_alloc()
341 * tb_path_free() - free a path
342 * @path: Path to free
344 * Frees a path. The path does not need to be deactivated.
346 void tb_path_free(struct tb_path *path) in tb_path_free() argument
350 for (i = 0; i < path->path_length; i++) { in tb_path_free()
351 const struct tb_path_hop *hop = &path->hops[i]; in tb_path_free()
361 kfree(path->hops); in tb_path_free()
362 kfree(path); in tb_path_free()
365 static void __tb_path_deallocate_nfc(struct tb_path *path, int first_hop) in __tb_path_deallocate_nfc() argument
368 for (i = first_hop; i < path->path_length; i++) { in __tb_path_deallocate_nfc()
369 res = tb_port_add_nfc_credits(path->hops[i].in_port, in __tb_path_deallocate_nfc()
370 -path->nfc_credits); in __tb_path_deallocate_nfc()
372 tb_port_warn(path->hops[i].in_port, in __tb_path_deallocate_nfc()
385 /* Disable the path */ in __tb_path_deactivate_hop()
428 static void __tb_path_deactivate_hops(struct tb_path *path, int first_hop) in __tb_path_deactivate_hops() argument
432 for (i = first_hop; i < path->path_length; i++) { in __tb_path_deactivate_hops()
433 res = __tb_path_deactivate_hop(path->hops[i].in_port, in __tb_path_deactivate_hops()
434 path->hops[i].in_hop_index, in __tb_path_deactivate_hops()
435 path->clear_fc); in __tb_path_deactivate_hops()
437 tb_port_warn(path->hops[i].in_port, in __tb_path_deactivate_hops()
439 i, path->hops[i].in_hop_index); in __tb_path_deactivate_hops()
443 void tb_path_deactivate(struct tb_path *path) in tb_path_deactivate() argument
445 if (!path->activated) { in tb_path_deactivate()
446 tb_WARN(path->tb, "trying to deactivate an inactive path\n"); in tb_path_deactivate()
449 tb_dbg(path->tb, in tb_path_deactivate()
450 "deactivating %s path from %llx:%x to %llx:%x\n", in tb_path_deactivate()
451 path->name, tb_route(path->hops[0].in_port->sw), in tb_path_deactivate()
452 path->hops[0].in_port->port, in tb_path_deactivate()
453 tb_route(path->hops[path->path_length - 1].out_port->sw), in tb_path_deactivate()
454 path->hops[path->path_length - 1].out_port->port); in tb_path_deactivate()
455 __tb_path_deactivate_hops(path, 0); in tb_path_deactivate()
456 __tb_path_deallocate_nfc(path, 0); in tb_path_deactivate()
457 path->activated = false; in tb_path_deactivate()
461 * tb_path_activate() - activate a path
463 * Activate a path starting with the last hop and iterating backwards. The
464 * caller must fill path->hops before calling tb_path_activate().
468 int tb_path_activate(struct tb_path *path) in tb_path_activate() argument
472 if (path->activated) { in tb_path_activate()
473 tb_WARN(path->tb, "trying to activate already activated path\n"); in tb_path_activate()
477 tb_dbg(path->tb, in tb_path_activate()
478 "activating %s path from %llx:%x to %llx:%x\n", in tb_path_activate()
479 path->name, tb_route(path->hops[0].in_port->sw), in tb_path_activate()
480 path->hops[0].in_port->port, in tb_path_activate()
481 tb_route(path->hops[path->path_length - 1].out_port->sw), in tb_path_activate()
482 path->hops[path->path_length - 1].out_port->port); in tb_path_activate()
485 for (i = path->path_length - 1; i >= 0; i--) { in tb_path_activate()
486 if (path->hops[i].in_counter_index == -1) in tb_path_activate()
488 res = tb_port_clear_counter(path->hops[i].in_port, in tb_path_activate()
489 path->hops[i].in_counter_index); in tb_path_activate()
495 for (i = path->path_length - 1; i >= 0; i--) { in tb_path_activate()
496 res = tb_port_add_nfc_credits(path->hops[i].in_port, in tb_path_activate()
497 path->nfc_credits); in tb_path_activate()
499 __tb_path_deallocate_nfc(path, i); in tb_path_activate()
505 for (i = path->path_length - 1; i >= 0; i--) { in tb_path_activate()
509 __tb_path_deactivate_hop(path->hops[i].in_port, in tb_path_activate()
510 path->hops[i].in_hop_index, path->clear_fc); in tb_path_activate()
513 hop.next_hop = path->hops[i].next_hop_index; in tb_path_activate()
514 hop.out_port = path->hops[i].out_port->port; in tb_path_activate()
515 hop.initial_credits = path->hops[i].initial_credits; in tb_path_activate()
520 out_mask = (i == path->path_length - 1) ? in tb_path_activate()
523 hop.weight = path->weight; in tb_path_activate()
525 hop.priority = path->priority; in tb_path_activate()
526 hop.drop_packages = path->drop_packages; in tb_path_activate()
527 hop.counter = path->hops[i].in_counter_index; in tb_path_activate()
528 hop.counter_enable = path->hops[i].in_counter_index != -1; in tb_path_activate()
529 hop.ingress_fc = path->ingress_fc_enable & in_mask; in tb_path_activate()
530 hop.egress_fc = path->egress_fc_enable & out_mask; in tb_path_activate()
531 hop.ingress_shared_buffer = path->ingress_shared_buffer in tb_path_activate()
533 hop.egress_shared_buffer = path->egress_shared_buffer in tb_path_activate()
537 tb_port_dbg(path->hops[i].in_port, "Writing hop %d\n", i); in tb_path_activate()
538 tb_dump_hop(&path->hops[i], &hop); in tb_path_activate()
539 res = tb_port_write(path->hops[i].in_port, &hop, TB_CFG_HOPS, in tb_path_activate()
540 2 * path->hops[i].in_hop_index, 2); in tb_path_activate()
542 __tb_path_deactivate_hops(path, i); in tb_path_activate()
543 __tb_path_deallocate_nfc(path, 0); in tb_path_activate()
547 path->activated = true; in tb_path_activate()
548 tb_dbg(path->tb, "path activation complete\n"); in tb_path_activate()
551 tb_WARN(path->tb, "path activation failed\n"); in tb_path_activate()
556 * tb_path_is_invalid() - check whether any ports on the path are invalid
558 * Return: Returns true if the path is invalid, false otherwise.
560 bool tb_path_is_invalid(struct tb_path *path) in tb_path_is_invalid() argument
563 for (i = 0; i < path->path_length; i++) { in tb_path_is_invalid()
564 if (path->hops[i].in_port->sw->is_unplugged) in tb_path_is_invalid()
566 if (path->hops[i].out_port->sw->is_unplugged) in tb_path_is_invalid()
573 * tb_path_port_on_path() - Does the path go through certain port
574 * @path: Path to check
577 * Goes over all hops on path and checks if @port is any of them.
580 bool tb_path_port_on_path(const struct tb_path *path, const struct tb_port *port) in tb_path_port_on_path() argument
584 for (i = 0; i < path->path_length; i++) { in tb_path_port_on_path()
585 if (path->hops[i].in_port == port || in tb_path_port_on_path()
586 path->hops[i].out_port == port) in tb_path_port_on_path()