From 0d0950a968009fd6e5c2a3763b2c6e81b3805b05 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 11 Jan 2023 08:26:31 +0200 Subject: [PATCH 1/3] net: thunderbolt: Move into own directory We will be adding tracepoints to the driver so instead of littering the main network driver directory, move the driver into its own directory. While there, rename the module to thunderbolt_net (with underscore) to match with the thunderbolt_dma_test convention. Signed-off-by: Mika Westerberg Acked-by: Yehezkel Bernat Signed-off-by: Jakub Kicinski --- MAINTAINERS | 2 +- drivers/net/Kconfig | 13 +------------ drivers/net/Makefile | 4 +--- drivers/net/thunderbolt/Kconfig | 12 ++++++++++++ drivers/net/thunderbolt/Makefile | 3 +++ drivers/net/{thunderbolt.c => thunderbolt/main.c} | 0 6 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 drivers/net/thunderbolt/Kconfig create mode 100644 drivers/net/thunderbolt/Makefile rename drivers/net/{thunderbolt.c => thunderbolt/main.c} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index c1062b42e680..c3d796e12bb8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20789,7 +20789,7 @@ M: Mika Westerberg M: Yehezkel Bernat L: netdev@vger.kernel.org S: Maintained -F: drivers/net/thunderbolt.c +F: drivers/net/thunderbolt/ THUNDERX GPIO DRIVER M: Robert Richter diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9e63b8c43f3e..950a09f021dd 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -583,18 +583,7 @@ config FUJITSU_ES This driver provides support for Extended Socket network device on Extended Partitioning of FUJITSU PRIMEQUEST 2000 E2 series. -config USB4_NET - tristate "Networking over USB4 and Thunderbolt cables" - depends on USB4 && INET - help - Select this if you want to create network between two computers - over a USB4 and Thunderbolt cables. The driver supports Apple - ThunderboltIP protocol and allows communication with any host - supporting the same protocol including Windows and macOS. - - To compile this driver a module, choose M here. The module will be - called thunderbolt-net. - +source "drivers/net/thunderbolt/Kconfig" source "drivers/net/hyperv/Kconfig" config NETDEVSIM diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6ce076462dbf..e26f98f897c5 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -84,8 +84,6 @@ obj-$(CONFIG_HYPERV_NET) += hyperv/ obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o obj-$(CONFIG_FUJITSU_ES) += fjes/ - -thunderbolt-net-y += thunderbolt.o -obj-$(CONFIG_USB4_NET) += thunderbolt-net.o +obj-$(CONFIG_USB4_NET) += thunderbolt/ obj-$(CONFIG_NETDEVSIM) += netdevsim/ obj-$(CONFIG_NET_FAILOVER) += net_failover.o diff --git a/drivers/net/thunderbolt/Kconfig b/drivers/net/thunderbolt/Kconfig new file mode 100644 index 000000000000..e127848c8cbd --- /dev/null +++ b/drivers/net/thunderbolt/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +config USB4_NET + tristate "Networking over USB4 and Thunderbolt cables" + depends on USB4 && INET + help + Select this if you want to create network between two computers + over a USB4 and Thunderbolt cables. The driver supports Apple + ThunderboltIP protocol and allows communication with any host + supporting the same protocol including Windows and macOS. + + To compile this driver a module, choose M here. The module will be + called thunderbolt_net. diff --git a/drivers/net/thunderbolt/Makefile b/drivers/net/thunderbolt/Makefile new file mode 100644 index 000000000000..dd644c8775d9 --- /dev/null +++ b/drivers/net/thunderbolt/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_USB4_NET) := thunderbolt_net.o +thunderbolt_net-objs := main.o diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt/main.c similarity index 100% rename from drivers/net/thunderbolt.c rename to drivers/net/thunderbolt/main.c From 7b3502c1598ae9dbac4f91af702e4e0d30337705 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 11 Jan 2023 08:26:32 +0200 Subject: [PATCH 2/3] net: thunderbolt: Add debugging when sending/receiving control packets These can be useful when debugging possible issues around USB4NET control packet exchange. Signed-off-by: Mika Westerberg Acked-by: Yehezkel Bernat Signed-off-by: Jakub Kicinski --- drivers/net/thunderbolt/main.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c index 990484776f2d..bd0c2af1172d 100644 --- a/drivers/net/thunderbolt/main.c +++ b/drivers/net/thunderbolt/main.c @@ -305,6 +305,8 @@ static int tbnet_logout_request(struct tbnet *net) static void start_login(struct tbnet *net) { + netdev_dbg(net->dev, "login started\n"); + mutex_lock(&net->connection_lock); net->login_sent = false; net->login_received = false; @@ -318,6 +320,8 @@ static void stop_login(struct tbnet *net) { cancel_delayed_work_sync(&net->login_work); cancel_work_sync(&net->connected_work); + + netdev_dbg(net->dev, "login stopped\n"); } static inline unsigned int tbnet_frame_size(const struct tbnet_frame *tf) @@ -374,6 +378,8 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout) int ret, retries = TBNET_LOGOUT_RETRIES; while (send_logout && retries-- > 0) { + netdev_dbg(net->dev, "sending logout request %u\n", + retries); ret = tbnet_logout_request(net); if (ret != -ETIMEDOUT) break; @@ -400,6 +406,8 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout) net->login_sent = false; net->login_received = false; + netdev_dbg(net->dev, "network traffic stopped\n"); + mutex_unlock(&net->connection_lock); } @@ -431,12 +439,15 @@ static int tbnet_handle_packet(const void *buf, size_t size, void *data) switch (pkg->hdr.type) { case TBIP_LOGIN: + netdev_dbg(net->dev, "remote login request received\n"); if (!netif_running(net->dev)) break; ret = tbnet_login_response(net, route, sequence, pkg->hdr.command_id); if (!ret) { + netdev_dbg(net->dev, "remote login response sent\n"); + mutex_lock(&net->connection_lock); net->login_received = true; net->remote_transmit_path = pkg->transmit_path; @@ -458,9 +469,12 @@ static int tbnet_handle_packet(const void *buf, size_t size, void *data) break; case TBIP_LOGOUT: + netdev_dbg(net->dev, "remote logout request received\n"); ret = tbnet_logout_response(net, route, sequence, command_id); - if (!ret) + if (!ret) { + netdev_dbg(net->dev, "remote logout response sent\n"); queue_work(system_long_wq, &net->disconnect_work); + } break; default: @@ -612,6 +626,8 @@ static void tbnet_connected_work(struct work_struct *work) if (!connected) return; + netdev_dbg(net->dev, "login successful, enabling paths\n"); + ret = tb_xdomain_alloc_in_hopid(net->xd, net->remote_transmit_path); if (ret != net->remote_transmit_path) { netdev_err(net->dev, "failed to allocate Rx HopID\n"); @@ -647,6 +663,8 @@ static void tbnet_connected_work(struct work_struct *work) netif_carrier_on(net->dev); netif_start_queue(net->dev); + + netdev_dbg(net->dev, "network traffic started\n"); return; err_free_tx_buffers: @@ -668,8 +686,13 @@ static void tbnet_login_work(struct work_struct *work) if (netif_carrier_ok(net->dev)) return; + netdev_dbg(net->dev, "sending login request, retries=%u\n", + net->login_retries); + ret = tbnet_login_request(net, net->login_retries % 4); if (ret) { + netdev_dbg(net->dev, "sending login request failed, ret=%d\n", + ret); if (net->login_retries++ < TBNET_LOGIN_RETRIES) { queue_delayed_work(system_long_wq, &net->login_work, delay); @@ -677,6 +700,8 @@ static void tbnet_login_work(struct work_struct *work) netdev_info(net->dev, "ThunderboltIP login timed out\n"); } } else { + netdev_dbg(net->dev, "received login reply\n"); + net->login_retries = 0; mutex_lock(&net->connection_lock); From f758652703803a1701d470de88158d5b8c70c9a4 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 11 Jan 2023 08:26:33 +0200 Subject: [PATCH 3/3] net: thunderbolt: Add tracepoints These are useful when debugging various performance issues. Signed-off-by: Mika Westerberg Acked-by: Yehezkel Bernat Signed-off-by: Jakub Kicinski --- drivers/net/thunderbolt/Makefile | 5 +- drivers/net/thunderbolt/main.c | 21 +++++ drivers/net/thunderbolt/trace.c | 10 +++ drivers/net/thunderbolt/trace.h | 141 +++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 drivers/net/thunderbolt/trace.c create mode 100644 drivers/net/thunderbolt/trace.h diff --git a/drivers/net/thunderbolt/Makefile b/drivers/net/thunderbolt/Makefile index dd644c8775d9..e81c2a4849f0 100644 --- a/drivers/net/thunderbolt/Makefile +++ b/drivers/net/thunderbolt/Makefile @@ -1,3 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_USB4_NET) := thunderbolt_net.o -thunderbolt_net-objs := main.o +thunderbolt_net-objs := main.o trace.o + +# Tracepoints need to know where to find trace.h +CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c index bd0c2af1172d..26ef3706445e 100644 --- a/drivers/net/thunderbolt/main.c +++ b/drivers/net/thunderbolt/main.c @@ -23,6 +23,8 @@ #include +#include "trace.h" + /* Protocol timeouts in ms */ #define TBNET_LOGIN_DELAY 4500 #define TBNET_LOGIN_TIMEOUT 500 @@ -353,6 +355,8 @@ static void tbnet_free_buffers(struct tbnet_ring *ring) size = TBNET_RX_PAGE_SIZE; } + trace_tbnet_free_frame(i, tf->page, tf->frame.buffer_phy, dir); + if (tf->frame.buffer_phy) dma_unmap_page(dma_dev, tf->frame.buffer_phy, size, dir); @@ -526,6 +530,9 @@ static int tbnet_alloc_rx_buffers(struct tbnet *net, unsigned int nbuffers) tf->frame.buffer_phy = dma_addr; tf->dev = net->dev; + trace_tbnet_alloc_rx_frame(index, tf->page, dma_addr, + DMA_FROM_DEVICE); + tb_ring_rx(ring->ring, &tf->frame); ring->prod++; @@ -602,6 +609,8 @@ static int tbnet_alloc_tx_buffers(struct tbnet *net) tf->frame.callback = tbnet_tx_callback; tf->frame.sof = TBIP_PDF_FRAME_START; tf->frame.eof = TBIP_PDF_FRAME_END; + + trace_tbnet_alloc_tx_frame(i, tf->page, dma_addr, DMA_TO_DEVICE); } ring->cons = 0; @@ -832,12 +841,16 @@ static int tbnet_poll(struct napi_struct *napi, int budget) hdr = page_address(page); if (!tbnet_check_frame(net, tf, hdr)) { + trace_tbnet_invalid_rx_ip_frame(hdr->frame_size, + hdr->frame_id, hdr->frame_index, hdr->frame_count); __free_pages(page, TBNET_RX_PAGE_ORDER); dev_kfree_skb_any(net->skb); net->skb = NULL; continue; } + trace_tbnet_rx_ip_frame(hdr->frame_size, hdr->frame_id, + hdr->frame_index, hdr->frame_count); frame_size = le32_to_cpu(hdr->frame_size); skb = net->skb; @@ -871,6 +884,7 @@ static int tbnet_poll(struct napi_struct *napi, int budget) if (last) { skb->protocol = eth_type_trans(skb, net->dev); + trace_tbnet_rx_skb(skb); napi_gro_receive(&net->napi, skb); net->skb = NULL; } @@ -990,6 +1004,8 @@ static bool tbnet_xmit_csum_and_map(struct tbnet *net, struct sk_buff *skb, for (i = 0; i < frame_count; i++) { hdr = page_address(frames[i]->page); hdr->frame_count = cpu_to_le32(frame_count); + trace_tbnet_tx_ip_frame(hdr->frame_size, hdr->frame_id, + hdr->frame_index, hdr->frame_count); dma_sync_single_for_device(dma_dev, frames[i]->frame.buffer_phy, tbnet_frame_size(frames[i]), DMA_TO_DEVICE); @@ -1054,6 +1070,8 @@ static bool tbnet_xmit_csum_and_map(struct tbnet *net, struct sk_buff *skb, len = le32_to_cpu(hdr->frame_size) - offset; wsum = csum_partial(dest, len, wsum); hdr->frame_count = cpu_to_le32(frame_count); + trace_tbnet_tx_ip_frame(hdr->frame_size, hdr->frame_id, + hdr->frame_index, hdr->frame_count); offset = 0; } @@ -1096,6 +1114,8 @@ static netdev_tx_t tbnet_start_xmit(struct sk_buff *skb, bool unmap = false; void *dest; + trace_tbnet_tx_skb(skb); + nframes = DIV_ROUND_UP(data_len, TBNET_MAX_PAYLOAD_SIZE); if (tbnet_available_buffers(&net->tx_ring) < nframes) { netif_stop_queue(net->dev); @@ -1202,6 +1222,7 @@ static netdev_tx_t tbnet_start_xmit(struct sk_buff *skb, net->stats.tx_packets++; net->stats.tx_bytes += skb->len; + trace_tbnet_consume_skb(skb); dev_consume_skb_any(skb); return NETDEV_TX_OK; diff --git a/drivers/net/thunderbolt/trace.c b/drivers/net/thunderbolt/trace.c new file mode 100644 index 000000000000..1b1499520a44 --- /dev/null +++ b/drivers/net/thunderbolt/trace.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Tracepoints for Thunderbolt/USB4 networking driver + * + * Copyright (C) 2023, Intel Corporation + * Author: Mika Westerberg + */ + +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/drivers/net/thunderbolt/trace.h b/drivers/net/thunderbolt/trace.h new file mode 100644 index 000000000000..9626eadaebb9 --- /dev/null +++ b/drivers/net/thunderbolt/trace.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Tracepoints for Thunderbolt/USB4 networking driver + * + * Copyright (C) 2023, Intel Corporation + * Author: Mika Westerberg + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM thunderbolt_net + +#if !defined(__TRACE_THUNDERBOLT_NET_H) || defined(TRACE_HEADER_MULTI_READ) +#define __TRACE_THUNDERBOLT_NET_H + +#include +#include +#include + +#define DMA_DATA_DIRECTION_NAMES \ + { DMA_BIDIRECTIONAL, "DMA_BIDIRECTIONAL" }, \ + { DMA_TO_DEVICE, "DMA_TO_DEVICE" }, \ + { DMA_FROM_DEVICE, "DMA_FROM_DEVICE" }, \ + { DMA_NONE, "DMA_NONE" } + +DECLARE_EVENT_CLASS(tbnet_frame, + TP_PROTO(unsigned int index, const void *page, dma_addr_t phys, + enum dma_data_direction dir), + TP_ARGS(index, page, phys, dir), + TP_STRUCT__entry( + __field(unsigned int, index) + __field(const void *, page) + __field(dma_addr_t, phys) + __field(enum dma_data_direction, dir) + ), + TP_fast_assign( + __entry->index = index; + __entry->page = page; + __entry->phys = phys; + __entry->dir = dir; + ), + TP_printk("index=%u page=%p phys=%pad dir=%s", + __entry->index, __entry->page, &__entry->phys, + __print_symbolic(__entry->dir, DMA_DATA_DIRECTION_NAMES)) +); + +DEFINE_EVENT(tbnet_frame, tbnet_alloc_rx_frame, + TP_PROTO(unsigned int index, const void *page, dma_addr_t phys, + enum dma_data_direction dir), + TP_ARGS(index, page, phys, dir) +); + +DEFINE_EVENT(tbnet_frame, tbnet_alloc_tx_frame, + TP_PROTO(unsigned int index, const void *page, dma_addr_t phys, + enum dma_data_direction dir), + TP_ARGS(index, page, phys, dir) +); + +DEFINE_EVENT(tbnet_frame, tbnet_free_frame, + TP_PROTO(unsigned int index, const void *page, dma_addr_t phys, + enum dma_data_direction dir), + TP_ARGS(index, page, phys, dir) +); + +DECLARE_EVENT_CLASS(tbnet_ip_frame, + TP_PROTO(__le32 size, __le16 id, __le16 index, __le32 count), + TP_ARGS(size, id, index, count), + TP_STRUCT__entry( + __field(u32, size) + __field(u16, id) + __field(u16, index) + __field(u32, count) + ), + TP_fast_assign( + __entry->size = le32_to_cpu(size); + __entry->id = le16_to_cpu(id); + __entry->index = le16_to_cpu(index); + __entry->count = le32_to_cpu(count); + ), + TP_printk("id=%u size=%u index=%u count=%u", + __entry->id, __entry->size, __entry->index, __entry->count) +); + +DEFINE_EVENT(tbnet_ip_frame, tbnet_rx_ip_frame, + TP_PROTO(__le32 size, __le16 id, __le16 index, __le32 count), + TP_ARGS(size, id, index, count) +); + +DEFINE_EVENT(tbnet_ip_frame, tbnet_invalid_rx_ip_frame, + TP_PROTO(__le32 size, __le16 id, __le16 index, __le32 count), + TP_ARGS(size, id, index, count) +); + +DEFINE_EVENT(tbnet_ip_frame, tbnet_tx_ip_frame, + TP_PROTO(__le32 size, __le16 id, __le16 index, __le32 count), + TP_ARGS(size, id, index, count) +); + +DECLARE_EVENT_CLASS(tbnet_skb, + TP_PROTO(const struct sk_buff *skb), + TP_ARGS(skb), + TP_STRUCT__entry( + __field(const void *, addr) + __field(unsigned int, len) + __field(unsigned int, data_len) + __field(unsigned int, nr_frags) + ), + TP_fast_assign( + __entry->addr = skb; + __entry->len = skb->len; + __entry->data_len = skb->data_len; + __entry->nr_frags = skb_shinfo(skb)->nr_frags; + ), + TP_printk("skb=%p len=%u data_len=%u nr_frags=%u", + __entry->addr, __entry->len, __entry->data_len, + __entry->nr_frags) +); + +DEFINE_EVENT(tbnet_skb, tbnet_rx_skb, + TP_PROTO(const struct sk_buff *skb), + TP_ARGS(skb) +); + +DEFINE_EVENT(tbnet_skb, tbnet_tx_skb, + TP_PROTO(const struct sk_buff *skb), + TP_ARGS(skb) +); + +DEFINE_EVENT(tbnet_skb, tbnet_consume_skb, + TP_PROTO(const struct sk_buff *skb), + TP_ARGS(skb) +); + +#endif /* _TRACE_THUNDERBOLT_NET_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +#include