From 4d989521a93bcabce7c18060d5cf98a207d56cbe Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 28 Feb 2025 04:50:19 -0800 Subject: [PATCH 01/16] netconsole: refactor CPU number formatting into separate function Extract CPU number formatting logic from prepare_extradata() into a new append_cpu_nr() function. This refactoring improves code organization by isolating CPU number formatting into its own function while reducing the complexity of prepare_extradata(). The change prepares the codebase for the upcoming taskname feature by establishing a consistent pattern for handling sysdata features. The CPU number formatting logic itself remains unchanged; only its location has moved to improve maintainability. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- drivers/net/netconsole.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 698dbbea2713..96153fd01f46 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -1117,13 +1117,21 @@ static void populate_configfs_item(struct netconsole_target *nt, init_target_config_group(nt, target_name); } +static int append_cpu_nr(struct netconsole_target *nt, int offset) +{ + /* Append cpu=%d at extradata_complete after userdata str */ + return scnprintf(&nt->extradata_complete[offset], + MAX_EXTRADATA_ENTRY_LEN, " cpu=%u\n", + raw_smp_processor_id()); +} + /* * prepare_extradata - append sysdata at extradata_complete in runtime * @nt: target to send message to */ static int prepare_extradata(struct netconsole_target *nt) { - int sysdata_len, extradata_len; + int extradata_len; /* userdata was appended when configfs write helper was called * by update_userdata(). @@ -1133,12 +1141,8 @@ static int prepare_extradata(struct netconsole_target *nt) if (!(nt->sysdata_fields & SYSDATA_CPU_NR)) goto out; - /* Append cpu=%d at extradata_complete after userdata str */ - sysdata_len = scnprintf(&nt->extradata_complete[nt->userdata_length], - MAX_EXTRADATA_ENTRY_LEN, " cpu=%u\n", - raw_smp_processor_id()); - - extradata_len += sysdata_len; + if (nt->sysdata_fields & SYSDATA_CPU_NR) + extradata_len += append_cpu_nr(nt, extradata_len); WARN_ON_ONCE(extradata_len > MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS); -- 2.51.0 From 33e4b29f2b3b7d013629bb86abe5cb726ec91199 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 28 Feb 2025 04:50:20 -0800 Subject: [PATCH 02/16] netconsole: add taskname to extradata entry count New SYSDATA_TASKNAME feature flag to track when taskname append is enabled. Additional check in count_extradata_entries() to include taskname in total, counting it as an entry in extradata. This function is used to check if we are not overflowing the number of extradata items. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- drivers/net/netconsole.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 96153fd01f46..f46a0edf9c11 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -104,6 +104,8 @@ struct netconsole_target_stats { enum sysdata_feature { /* Populate the CPU that sends the message */ SYSDATA_CPU_NR = BIT(0), + /* Populate the task name (as in current->comm) in sysdata */ + SYSDATA_TASKNAME = BIT(1), }; /** @@ -701,6 +703,8 @@ static size_t count_extradata_entries(struct netconsole_target *nt) /* Plus sysdata entries */ if (nt->sysdata_fields & SYSDATA_CPU_NR) entries += 1; + if (nt->sysdata_fields & SYSDATA_TASKNAME) + entries += 1; return entries; } -- 2.51.0 From 09e877590bc28ae897b10f6b1becc29786fe1bd4 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 28 Feb 2025 04:50:21 -0800 Subject: [PATCH 03/16] netconsole: add configfs controls for taskname sysdata feature Add configfs interface to enable/disable the taskname sysdata feature. This adds the following functionality: The implementation follows the same pattern as the existing CPU number feature, ensuring consistent behavior and error handling across sysdata features. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- drivers/net/netconsole.c | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index f46a0edf9c11..9798b2b409e2 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -426,6 +426,20 @@ static ssize_t sysdata_cpu_nr_enabled_show(struct config_item *item, char *buf) return sysfs_emit(buf, "%d\n", cpu_nr_enabled); } +/* configfs helper to display if taskname sysdata feature is enabled */ +static ssize_t sysdata_taskname_enabled_show(struct config_item *item, + char *buf) +{ + struct netconsole_target *nt = to_target(item->ci_parent); + bool taskname_enabled; + + mutex_lock(&dynamic_netconsole_mutex); + taskname_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME); + mutex_unlock(&dynamic_netconsole_mutex); + + return sysfs_emit(buf, "%d\n", taskname_enabled); +} + /* * This one is special -- targets created through the configfs interface * are not enabled (and the corresponding netpoll activated) by default. @@ -841,6 +855,40 @@ static void disable_sysdata_feature(struct netconsole_target *nt, nt->extradata_complete[nt->userdata_length] = 0; } +static ssize_t sysdata_taskname_enabled_store(struct config_item *item, + const char *buf, size_t count) +{ + struct netconsole_target *nt = to_target(item->ci_parent); + bool taskname_enabled, curr; + ssize_t ret; + + ret = kstrtobool(buf, &taskname_enabled); + if (ret) + return ret; + + mutex_lock(&dynamic_netconsole_mutex); + curr = !!(nt->sysdata_fields & SYSDATA_TASKNAME); + if (taskname_enabled == curr) + goto unlock_ok; + + if (taskname_enabled && + count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) { + ret = -ENOSPC; + goto unlock; + } + + if (taskname_enabled) + nt->sysdata_fields |= SYSDATA_TASKNAME; + else + disable_sysdata_feature(nt, SYSDATA_TASKNAME); + +unlock_ok: + ret = strnlen(buf, count); +unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return ret; +} + /* configfs helper to sysdata cpu_nr feature */ static ssize_t sysdata_cpu_nr_enabled_store(struct config_item *item, const char *buf, size_t count) @@ -886,6 +934,7 @@ unlock: CONFIGFS_ATTR(userdatum_, value); CONFIGFS_ATTR(sysdata_, cpu_nr_enabled); +CONFIGFS_ATTR(sysdata_, taskname_enabled); static struct configfs_attribute *userdatum_attrs[] = { &userdatum_attr_value, @@ -946,6 +995,7 @@ static void userdatum_drop(struct config_group *group, struct config_item *item) static struct configfs_attribute *userdata_attrs[] = { &sysdata_attr_cpu_nr_enabled, + &sysdata_attr_taskname_enabled, NULL, }; -- 2.51.0 From dd30ae533242495a724b37066cae1fb03ee6b601 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 28 Feb 2025 04:50:22 -0800 Subject: [PATCH 04/16] netconsole: add task name to extra data fields This is the core patch for this whole patchset. Add support for including the current task's name in netconsole's extra data output. This adds a new append_taskname() function that writes the task name (from current->comm) into the target's extradata buffer, similar to how CPU numbers are handled. The task name is included when the SYSDATA_TASKNAME field is set, appearing in the format "taskname=" in the output. This additional context can help with debugging by showing which task generated each console message. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- drivers/net/netconsole.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 9798b2b409e2..098ea9eb0237 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -1179,12 +1179,19 @@ static int append_cpu_nr(struct netconsole_target *nt, int offset) raw_smp_processor_id()); } +static int append_taskname(struct netconsole_target *nt, int offset) +{ + return scnprintf(&nt->extradata_complete[offset], + MAX_EXTRADATA_ENTRY_LEN, " taskname=%s\n", + current->comm); +} /* * prepare_extradata - append sysdata at extradata_complete in runtime * @nt: target to send message to */ static int prepare_extradata(struct netconsole_target *nt) { + u32 fields = SYSDATA_CPU_NR | SYSDATA_TASKNAME; int extradata_len; /* userdata was appended when configfs write helper was called @@ -1192,11 +1199,13 @@ static int prepare_extradata(struct netconsole_target *nt) */ extradata_len = nt->userdata_length; - if (!(nt->sysdata_fields & SYSDATA_CPU_NR)) + if (!(nt->sysdata_fields & fields)) goto out; if (nt->sysdata_fields & SYSDATA_CPU_NR) extradata_len += append_cpu_nr(nt, extradata_len); + if (nt->sysdata_fields & SYSDATA_TASKNAME) + extradata_len += append_taskname(nt, extradata_len); WARN_ON_ONCE(extradata_len > MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS); -- 2.51.0 From 7010b619830f639bdb930ed1da3766fbb379d5dc Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 28 Feb 2025 04:50:23 -0800 Subject: [PATCH 05/16] netconsole: docs: document the task name feature Add documentation for the netconsole task name feature in Documentation/networking/netconsole.rst. This explains how to enable task name via configfs and demonstrates the output format. The documentation includes: - How to enable/disable the feature via taskname_enabled - The format of the task name in the output - An example showing the task name appearing in messages Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- Documentation/networking/netconsole.rst | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Documentation/networking/netconsole.rst b/Documentation/networking/netconsole.rst index 84803c59968a..ae82a6337a8d 100644 --- a/Documentation/networking/netconsole.rst +++ b/Documentation/networking/netconsole.rst @@ -240,6 +240,34 @@ Delete `userdata` entries with `rmdir`:: It is recommended to not write user data values with newlines. +Task name auto population in userdata +------------------------------------- + +Inside the netconsole configfs hierarchy, there is a file called +`taskname_enabled` under the `userdata` directory. This file is used to enable +or disable the automatic task name population feature. This feature +automatically populates the current task name that is scheduled in the CPU +sneding the message. + +To enable task name auto-population:: + + echo 1 > /sys/kernel/config/netconsole/target1/userdata/taskname_enabled + +When this option is enabled, the netconsole messages will include an additional +line in the userdata field with the format `taskname=`. This allows +the receiver of the netconsole messages to easily find which application was +currently scheduled when that message was generated, providing extra context +for kernel messages and helping to categorize them. + +Example:: + + echo "This is a message" > /dev/kmsg + 12,607,22085407756,-;This is a message + taskname=echo + +In this example, the message was generated while "echo" was the current +scheduled process. + CPU number auto population in userdata -------------------------------------- -- 2.51.0 From d7a2522426e86036f40fde6ba055aa20de1f3d8a Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 28 Feb 2025 04:50:24 -0800 Subject: [PATCH 06/16] netconsole: selftest: add task name append testing Add test coverage for the netconsole task name feature to the existing sysdata selftest script. This extends the test infrastructure to verify that task names are correctly appended when enabled and absent when disabled. The test validates that: - Task names appear in the expected format "taskname=" - Task names are included when the feature is enabled - Task names are excluded when the feature is disabled - The feature works correctly alongside other sysdata fields like CPU Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- .../selftests/drivers/net/netcons_sysdata.sh | 51 ++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/drivers/net/netcons_sysdata.sh b/tools/testing/selftests/drivers/net/netcons_sysdata.sh index 2b78fd1f5982..f351206ed1bd 100755 --- a/tools/testing/selftests/drivers/net/netcons_sysdata.sh +++ b/tools/testing/selftests/drivers/net/netcons_sysdata.sh @@ -31,17 +31,38 @@ function set_cpu_nr() { echo 1 > "${NETCONS_PATH}/userdata/cpu_nr_enabled" } +# Enable the taskname to be appended to sysdata +function set_taskname() { + if [[ ! -f "${NETCONS_PATH}/userdata/taskname_enabled" ]] + then + echo "Not able to enable taskname sysdata append. Configfs not available in ${NETCONS_PATH}/userdata/taskname_enabled" >&2 + exit "${ksft_skip}" + fi + + echo 1 > "${NETCONS_PATH}/userdata/taskname_enabled" +} + # Disable the sysdata cpu_nr feature function unset_cpu_nr() { echo 0 > "${NETCONS_PATH}/userdata/cpu_nr_enabled" } -# Test if MSG content and `cpu=${CPU}` exists in OUTPUT_FILE -function validate_sysdata_cpu_exists() { +# Once called, taskname=<..> will not be appended anymore +function unset_taskname() { + echo 0 > "${NETCONS_PATH}/userdata/taskname_enabled" +} + +# Test if MSG contains sysdata +function validate_sysdata() { # OUTPUT_FILE will contain something like: # 6.11.1-0_fbk0_rc13_509_g30d75cea12f7,13,1822,115075213798,-;netconsole selftest: netcons_gtJHM # userdatakey=userdatavalue # cpu=X + # taskname= + + # Echo is what this test uses to create the message. See runtest() + # function + SENDER="echo" if [ ! -f "$OUTPUT_FILE" ]; then echo "FAIL: File was not generated." >&2 @@ -62,12 +83,19 @@ function validate_sysdata_cpu_exists() { exit "${ksft_fail}" fi + if ! grep -q "taskname=${SENDER}" "${OUTPUT_FILE}"; then + echo "FAIL: 'taskname=echo' not found in ${OUTPUT_FILE}" >&2 + cat "${OUTPUT_FILE}" >&2 + exit "${ksft_fail}" + fi + rm "${OUTPUT_FILE}" pkill_socat } -# Test if MSG content exists in OUTPUT_FILE but no `cpu=` string -function validate_sysdata_no_cpu() { +# Test if MSG content exists in OUTPUT_FILE but no `cpu=` and `taskname=` +# strings +function validate_no_sysdata() { if [ ! -f "$OUTPUT_FILE" ]; then echo "FAIL: File was not generated." >&2 exit "${ksft_fail}" @@ -85,6 +113,12 @@ function validate_sysdata_no_cpu() { exit "${ksft_fail}" fi + if grep -q "taskname=" "${OUTPUT_FILE}"; then + echo "FAIL: 'taskname= found in ${OUTPUT_FILE}" >&2 + cat "${OUTPUT_FILE}" >&2 + exit "${ksft_fail}" + fi + rm "${OUTPUT_FILE}" } @@ -133,10 +167,12 @@ OUTPUT_FILE="/tmp/${TARGET}_1" MSG="Test #1 from CPU${CPU}" # Enable the auto population of cpu_nr set_cpu_nr +# Enable taskname to be appended to sysdata +set_taskname runtest # Make sure the message was received in the dst part # and exit -validate_sysdata_cpu_exists +validate_sysdata #==================================================== # TEST #2 @@ -148,7 +184,7 @@ OUTPUT_FILE="/tmp/${TARGET}_2" MSG="Test #2 from CPU${CPU}" set_user_data runtest -validate_sysdata_cpu_exists +validate_sysdata # =================================================== # TEST #3 @@ -160,8 +196,9 @@ OUTPUT_FILE="/tmp/${TARGET}_3" MSG="Test #3 from CPU${CPU}" # Enable the auto population of cpu_nr unset_cpu_nr +unset_taskname runtest # At this time, cpu= shouldn't be present in the msg -validate_sysdata_no_cpu +validate_no_sysdata exit "${ksft_pass}" -- 2.51.0 From 00f5e338cf7e2612ecf66d07b391135dd32f74e1 Mon Sep 17 00:00:00 2001 From: Gang Yan Date: Fri, 28 Feb 2025 15:38:35 +0100 Subject: [PATCH 07/16] selftests: mptcp: Add a tool to get specific msk_info This patch enables the retrieval of the mptcp_info structure corresponding to a specified MPTCP socket (msk). When multiple MPTCP connections are present, specific information can be obtained for a given connection through the 'mptcp_diag_dump_one' by using the 'token' associated with the msk. Signed-off-by: Gang Yan Co-developed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250228-net-next-mptcp-coverage-small-opti-v1-1-f933c4275676@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/mptcp/Makefile | 2 +- .../testing/selftests/net/mptcp/mptcp_diag.c | 272 ++++++++++++++++++ 2 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/net/mptcp/mptcp_diag.c diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile index c76525fe2b84..340e1a777e16 100644 --- a/tools/testing/selftests/net/mptcp/Makefile +++ b/tools/testing/selftests/net/mptcp/Makefile @@ -7,7 +7,7 @@ CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INC TEST_PROGS := mptcp_connect.sh pm_netlink.sh mptcp_join.sh diag.sh \ simult_flows.sh mptcp_sockopt.sh userspace_pm.sh -TEST_GEN_FILES = mptcp_connect pm_nl_ctl mptcp_sockopt mptcp_inq +TEST_GEN_FILES = mptcp_connect pm_nl_ctl mptcp_sockopt mptcp_inq mptcp_diag TEST_FILES := mptcp_lib.sh settings diff --git a/tools/testing/selftests/net/mptcp/mptcp_diag.c b/tools/testing/selftests/net/mptcp/mptcp_diag.c new file mode 100644 index 000000000000..284286c524cf --- /dev/null +++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025, Kylin Software */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif + +struct mptcp_info { + __u8 mptcpi_subflows; + __u8 mptcpi_add_addr_signal; + __u8 mptcpi_add_addr_accepted; + __u8 mptcpi_subflows_max; + __u8 mptcpi_add_addr_signal_max; + __u8 mptcpi_add_addr_accepted_max; + __u32 mptcpi_flags; + __u32 mptcpi_token; + __u64 mptcpi_write_seq; + __u64 mptcpi_snd_una; + __u64 mptcpi_rcv_nxt; + __u8 mptcpi_local_addr_used; + __u8 mptcpi_local_addr_max; + __u8 mptcpi_csum_enabled; + __u32 mptcpi_retransmits; + __u64 mptcpi_bytes_retrans; + __u64 mptcpi_bytes_sent; + __u64 mptcpi_bytes_received; + __u64 mptcpi_bytes_acked; + __u8 mptcpi_subflows_total; + __u8 reserved[3]; + __u32 mptcpi_last_data_sent; + __u32 mptcpi_last_data_recv; + __u32 mptcpi_last_ack_recv; +}; + +static void die_perror(const char *msg) +{ + perror(msg); + exit(1); +} + +static void die_usage(int r) +{ + fprintf(stderr, "Usage: mptcp_diag -t\n"); + exit(r); +} + +static void send_query(int fd, __u32 token) +{ + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK + }; + struct { + struct nlmsghdr nlh; + struct inet_diag_req_v2 r; + } req = { + .nlh = { + .nlmsg_len = sizeof(req), + .nlmsg_type = SOCK_DIAG_BY_FAMILY, + .nlmsg_flags = NLM_F_REQUEST + }, + .r = { + .sdiag_family = AF_INET, + /* Real proto is set via INET_DIAG_REQ_PROTOCOL */ + .sdiag_protocol = IPPROTO_TCP, + .id.idiag_cookie[0] = token, + } + }; + struct rtattr rta_proto; + struct iovec iov[6]; + int iovlen = 1; + __u32 proto; + + req.r.idiag_ext |= (1 << (INET_DIAG_INFO - 1)); + proto = IPPROTO_MPTCP; + rta_proto.rta_type = INET_DIAG_REQ_PROTOCOL; + rta_proto.rta_len = RTA_LENGTH(sizeof(proto)); + + iov[0] = (struct iovec) { + .iov_base = &req, + .iov_len = sizeof(req) + }; + iov[iovlen] = (struct iovec){ &rta_proto, sizeof(rta_proto)}; + iov[iovlen + 1] = (struct iovec){ &proto, sizeof(proto)}; + req.nlh.nlmsg_len += RTA_LENGTH(sizeof(proto)); + iovlen += 2; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = iov, + .msg_iovlen = iovlen + }; + + for (;;) { + if (sendmsg(fd, &msg, 0) < 0) { + if (errno == EINTR) + continue; + die_perror("sendmsg"); + } + break; + } +} + +static void parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, + int len, unsigned short flags) +{ + unsigned short type; + + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + while (RTA_OK(rta, len)) { + type = rta->rta_type & ~flags; + if (type <= max && !tb[type]) + tb[type] = rta; + rta = RTA_NEXT(rta, len); + } +} + +static void print_info_msg(struct mptcp_info *info) +{ + printf("Token & Flags\n"); + printf("token: %x\n", info->mptcpi_token); + printf("flags: %x\n", info->mptcpi_flags); + printf("csum_enabled: %u\n", info->mptcpi_csum_enabled); + + printf("\nBasic Info\n"); + printf("subflows: %u\n", info->mptcpi_subflows); + printf("subflows_max: %u\n", info->mptcpi_subflows_max); + printf("subflows_total: %u\n", info->mptcpi_subflows_total); + printf("local_addr_used: %u\n", info->mptcpi_local_addr_used); + printf("local_addr_max: %u\n", info->mptcpi_local_addr_max); + printf("add_addr_signal: %u\n", info->mptcpi_add_addr_signal); + printf("add_addr_accepted: %u\n", info->mptcpi_add_addr_accepted); + printf("add_addr_signal_max: %u\n", info->mptcpi_add_addr_signal_max); + printf("add_addr_accepted_max: %u\n", info->mptcpi_add_addr_accepted_max); + + printf("\nTransmission Info\n"); + printf("write_seq: %llu\n", info->mptcpi_write_seq); + printf("snd_una: %llu\n", info->mptcpi_snd_una); + printf("rcv_nxt: %llu\n", info->mptcpi_rcv_nxt); + printf("last_data_sent: %u\n", info->mptcpi_last_data_sent); + printf("last_data_recv: %u\n", info->mptcpi_last_data_recv); + printf("last_ack_recv: %u\n", info->mptcpi_last_ack_recv); + printf("retransmits: %u\n", info->mptcpi_retransmits); + printf("retransmit bytes: %llu\n", info->mptcpi_bytes_retrans); + printf("bytes_sent: %llu\n", info->mptcpi_bytes_sent); + printf("bytes_received: %llu\n", info->mptcpi_bytes_received); + printf("bytes_acked: %llu\n", info->mptcpi_bytes_acked); +} + +static void parse_nlmsg(struct nlmsghdr *nlh) +{ + struct inet_diag_msg *r = NLMSG_DATA(nlh); + struct rtattr *tb[INET_DIAG_MAX + 1]; + + parse_rtattr_flags(tb, INET_DIAG_MAX, (struct rtattr *)(r + 1), + nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)), + NLA_F_NESTED); + + if (tb[INET_DIAG_INFO]) { + int len = RTA_PAYLOAD(tb[INET_DIAG_INFO]); + struct mptcp_info *info; + + /* workaround fort older kernels with less fields */ + if (len < sizeof(*info)) { + info = alloca(sizeof(*info)); + memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len); + memset((char *)info + len, 0, sizeof(*info) - len); + } else { + info = RTA_DATA(tb[INET_DIAG_INFO]); + } + print_info_msg(info); + } +} + +static void recv_nlmsg(int fd, struct nlmsghdr *nlh) +{ + char rcv_buff[8192]; + struct sockaddr_nl rcv_nladdr = { + .nl_family = AF_NETLINK + }; + struct iovec rcv_iov = { + .iov_base = rcv_buff, + .iov_len = sizeof(rcv_buff) + }; + struct msghdr rcv_msg = { + .msg_name = &rcv_nladdr, + .msg_namelen = sizeof(rcv_nladdr), + .msg_iov = &rcv_iov, + .msg_iovlen = 1 + }; + int len; + + len = recvmsg(fd, &rcv_msg, 0); + nlh = (struct nlmsghdr *)rcv_buff; + + while (NLMSG_OK(nlh, len)) { + if (nlh->nlmsg_type == NLMSG_DONE) { + printf("NLMSG_DONE\n"); + break; + } else if (nlh->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err; + + err = (struct nlmsgerr *)NLMSG_DATA(nlh); + printf("Error %d:%s\n", + -(err->error), strerror(-(err->error))); + break; + } + parse_nlmsg(nlh); + nlh = NLMSG_NEXT(nlh, len); + } +} + +static void get_mptcpinfo(__u32 token) +{ + struct nlmsghdr *nlh = NULL; + int fd; + + fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG); + if (fd < 0) + die_perror("Netlink socket"); + + send_query(fd, token); + recv_nlmsg(fd, nlh); + + close(fd); +} + +static void parse_opts(int argc, char **argv, __u32 *target_token) +{ + int c; + + if (argc < 2) + die_usage(1); + + while ((c = getopt(argc, argv, "ht:")) != -1) { + switch (c) { + case 'h': + die_usage(0); + break; + case 't': + sscanf(optarg, "%x", target_token); + break; + default: + die_usage(1); + break; + } + } +} + +int main(int argc, char *argv[]) +{ + __u32 target_token; + + parse_opts(argc, argv, &target_token); + get_mptcpinfo(target_token); + + return 0; +} + -- 2.51.0 From ba24001665704d27976a2f190cd8361e339f8581 Mon Sep 17 00:00:00 2001 From: Gang Yan Date: Fri, 28 Feb 2025 15:38:36 +0100 Subject: [PATCH 08/16] selftests: mptcp: add a test for mptcp_diag_dump_one This patch introduces a new 'chk_diag' test in diag.sh. It retrieves the token for a specified MPTCP socket (msk) using the 'ss' command and then accesses the 'mptcp_diag_dump_one' in kernel via ./mptcp_diag to verify if the correct token is returned. Link: https://github.com/multipath-tcp/mptcp_net-next/issues/524 Signed-off-by: Gang Yan Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250228-net-next-mptcp-coverage-small-opti-v1-2-f933c4275676@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/mptcp/diag.sh | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh index 2bd0c1eb70c5..4f55477ffe08 100755 --- a/tools/testing/selftests/net/mptcp/diag.sh +++ b/tools/testing/selftests/net/mptcp/diag.sh @@ -200,6 +200,32 @@ chk_msk_cestab() "${expected}" "${msg}" "" } +chk_dump_one() +{ + local ss_token + local token + local msg + + ss_token="$(ss -inmHMN $ns | grep 'token:' |\ + head -n 1 |\ + sed 's/.*token:\([0-9a-f]*\).*/\1/')" + + token="$(ip netns exec $ns ./mptcp_diag -t $ss_token |\ + awk -F':[ \t]+' '/^token/ {print $2}')" + + msg="....chk dump_one" + + mptcp_lib_print_title "$msg" + if [ -n "$ss_token" ] && [ "$ss_token" = "$token" ]; then + mptcp_lib_pr_ok + mptcp_lib_result_pass "${msg}" + else + mptcp_lib_pr_fail "expected $ss_token found $token" + mptcp_lib_result_fail "${msg}" + ret=${KSFT_FAIL} + fi +} + msk_info_get_value() { local port="${1}" @@ -290,6 +316,7 @@ chk_msk_remote_key_nr 2 "....chk remote_key" chk_msk_fallback_nr 0 "....chk no fallback" chk_msk_inuse 2 chk_msk_cestab 2 +chk_dump_one flush_pids chk_msk_inuse 0 "2->0" -- 2.51.0 From e85d33b35508da7e7570c0b54f007b59e205f623 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 28 Feb 2025 15:38:37 +0100 Subject: [PATCH 09/16] mptcp: pm: in-kernel: avoid access entry without lock In mptcp_pm_nl_set_flags(), "entry" is copied to "local" when pernet->lock is held to avoid direct access to entry without pernet->lock. Therefore, "local->flags" should be passed to mptcp_nl_set_flags instead of "entry->flags" when pernet->lock is not held, so as to avoid access to entry. Signed-off-by: Geliang Tang Fixes: 145dc6cc4abd ("mptcp: pm: change to fullmesh only for 'subflow'") Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250228-net-next-mptcp-coverage-small-opti-v1-3-f933c4275676@kernel.org Signed-off-by: Jakub Kicinski --- net/mptcp/pm_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index d4328443d844..fb83eba041f1 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -1983,7 +1983,7 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local, *local = *entry; spin_unlock_bh(&pernet->lock); - mptcp_nl_set_flags(net, &local->addr, entry->flags, changed); + mptcp_nl_set_flags(net, &local->addr, local->flags, changed); return 0; } -- 2.51.0 From 70c575d5a94f4817d839a2ef1e0a10b1fbd6383e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 28 Feb 2025 15:38:38 +0100 Subject: [PATCH 10/16] mptcp: pm: in-kernel: reduce parameters of set_flags The number of parameters in mptcp_nl_set_flags() can be reduced. Only need to pass a "local" parameter to it instead of "local->addr" and "local->flags". Signed-off-by: Geliang Tang Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250228-net-next-mptcp-coverage-small-opti-v1-4-f933c4275676@kernel.org Signed-off-by: Jakub Kicinski --- net/mptcp/pm_netlink.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index fb83eba041f1..4bebc4963c42 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -1907,11 +1907,12 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk, spin_unlock_bh(&msk->pm.lock); } -static void mptcp_nl_set_flags(struct net *net, struct mptcp_addr_info *addr, - u8 flags, u8 changed) +static void mptcp_nl_set_flags(struct net *net, + struct mptcp_pm_addr_entry *local, + u8 changed) { - u8 is_subflow = !!(flags & MPTCP_PM_ADDR_FLAG_SUBFLOW); - u8 bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP); + u8 is_subflow = !!(local->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW); + u8 bkup = !!(local->flags & MPTCP_PM_ADDR_FLAG_BACKUP); long s_slot = 0, s_num = 0; struct mptcp_sock *msk; @@ -1926,10 +1927,10 @@ static void mptcp_nl_set_flags(struct net *net, struct mptcp_addr_info *addr, lock_sock(sk); if (changed & MPTCP_PM_ADDR_FLAG_BACKUP) - mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup); + mptcp_pm_nl_mp_prio_send_ack(msk, &local->addr, NULL, bkup); /* Subflows will only be recreated if the SUBFLOW flag is set */ if (is_subflow && (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)) - mptcp_pm_nl_fullmesh(msk, addr); + mptcp_pm_nl_fullmesh(msk, &local->addr); release_sock(sk); next: @@ -1983,7 +1984,7 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local, *local = *entry; spin_unlock_bh(&pernet->lock); - mptcp_nl_set_flags(net, &local->addr, local->flags, changed); + mptcp_nl_set_flags(net, local, changed); return 0; } -- 2.51.0 From f0de92479a098ba930506ed2e715a7aad3887ec1 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Fri, 28 Feb 2025 15:38:39 +0100 Subject: [PATCH 11/16] mptcp: pm: exit early with ADD_ADDR echo if possible When the userspace PM is used, or when the in-kernel limits are reached, there will be no need to schedule the PM worker to signal new addresses. That corresponds to pm->work_pending set to 0. In this case, an early exit can be done in mptcp_pm_add_addr_echoed() not to hold the PM lock, and iterate over the announced addresses list, not to schedule the worker anyway in this case. This is similar to what is done when a connection or a subflow has been established. Reviewed-by: Geliang Tang Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250228-net-next-mptcp-coverage-small-opti-v1-5-f933c4275676@kernel.org Signed-off-by: Jakub Kicinski --- net/mptcp/pm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 16cacce6c10f..6c8cadf84f31 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -251,6 +251,9 @@ void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk, pr_debug("msk=%p\n", msk); + if (!READ_ONCE(pm->work_pending)) + return; + spin_lock_bh(&pm->lock); if (mptcp_lookup_anno_list_by_saddr(msk, addr) && READ_ONCE(pm->work_pending)) -- 2.51.0 From 39e912a959c19338855b768eaaee2917d7841f71 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Fri, 28 Feb 2025 15:02:10 +0000 Subject: [PATCH 12/16] dpll: Add an assertion to check freq_supported_num Since the driver is broken in the case that src->freq_supported is not NULL but src->freq_supported_num is 0, add an assertion for it. Signed-off-by: Jiasheng Jiang Reviewed-by: Jiri Pirko Reviewed-by: Vadim Fedorenko Reviewed-by: Arkadiusz Kubalewski Link: https://patch.msgid.link/20250228150210.34404-1-jiashengjiangcool@gmail.com Signed-off-by: Jakub Kicinski --- drivers/dpll/dpll_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 32019dc33cca..940c26b9dd53 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -443,8 +443,11 @@ static void dpll_pin_prop_free(struct dpll_pin_properties *prop) static int dpll_pin_prop_dup(const struct dpll_pin_properties *src, struct dpll_pin_properties *dst) { + if (WARN_ON(src->freq_supported && !src->freq_supported_num)) + return -EINVAL; + memcpy(dst, src, sizeof(*dst)); - if (src->freq_supported && src->freq_supported_num) { + if (src->freq_supported) { size_t freq_size = src->freq_supported_num * sizeof(*src->freq_supported); dst->freq_supported = kmemdup(src->freq_supported, -- 2.51.0 From a06a868a0cd96bc51401cdea897313a3f6ad01a0 Mon Sep 17 00:00:00 2001 From: Andrei Botila Date: Fri, 28 Feb 2025 17:43:19 +0200 Subject: [PATCH 13/16] net: phy: nxp-c45-tja11xx: add match_phy_device to TJA1103/TJA1104 Add .match_phy_device for the existing TJAs to differentiate between TJA1103 and TJA1104. TJA1103 and TJA1104 share the same PHY_ID but TJA1104 has MACsec capabilities while TJA1103 doesn't. Signed-off-by: Andrei Botila Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250228154320.2979000-2-andrei.botila@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 54 +++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 34231b5b9175..4013a17c205a 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* NXP C45 PHY driver - * Copyright 2021-2023 NXP + * Copyright 2021-2025 NXP * Author: Radu Pirea */ @@ -19,6 +19,8 @@ #include "nxp-c45-tja11xx.h" +#define PHY_ID_MASK GENMASK(31, 4) +/* Same id: TJA1103, TJA1104 */ #define PHY_ID_TJA_1103 0x001BB010 #define PHY_ID_TJA_1120 0x001BB031 @@ -1888,6 +1890,30 @@ static void tja1120_nmi_handler(struct phy_device *phydev, } } +static int nxp_c45_macsec_ability(struct phy_device *phydev) +{ + bool macsec_ability; + int phy_abilities; + + phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_ABILITIES); + macsec_ability = !!(phy_abilities & MACSEC_ABILITY); + + return macsec_ability; +} + +static int tja1103_match_phy_device(struct phy_device *phydev) +{ + return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && + !nxp_c45_macsec_ability(phydev); +} + +static int tja1104_match_phy_device(struct phy_device *phydev) +{ + return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && + nxp_c45_macsec_ability(phydev); +} + static const struct nxp_c45_regmap tja1120_regmap = { .vend1_ptp_clk_period = 0x1020, .vend1_event_msg_filt = 0x9010, @@ -1958,7 +1984,6 @@ static const struct nxp_c45_phy_data tja1120_phy_data = { static struct phy_driver nxp_c45_driver[] = { { - PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), .name = "NXP C45 TJA1103", .get_features = nxp_c45_get_features, .driver_data = &tja1103_phy_data, @@ -1980,6 +2005,31 @@ static struct phy_driver nxp_c45_driver[] = { .get_sqi = nxp_c45_get_sqi, .get_sqi_max = nxp_c45_get_sqi_max, .remove = nxp_c45_remove, + .match_phy_device = tja1103_match_phy_device, + }, + { + .name = "NXP C45 TJA1104", + .get_features = nxp_c45_get_features, + .driver_data = &tja1103_phy_data, + .probe = nxp_c45_probe, + .soft_reset = nxp_c45_soft_reset, + .config_aneg = genphy_c45_config_aneg, + .config_init = nxp_c45_config_init, + .config_intr = tja1103_config_intr, + .handle_interrupt = nxp_c45_handle_interrupt, + .read_status = genphy_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = genphy_c45_pma_resume, + .get_sset_count = nxp_c45_get_sset_count, + .get_strings = nxp_c45_get_strings, + .get_stats = nxp_c45_get_stats, + .cable_test_start = nxp_c45_cable_test_start, + .cable_test_get_status = nxp_c45_cable_test_get_status, + .set_loopback = genphy_c45_loopback, + .get_sqi = nxp_c45_get_sqi, + .get_sqi_max = nxp_c45_get_sqi_max, + .remove = nxp_c45_remove, + .match_phy_device = tja1104_match_phy_device, }, { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), -- 2.51.0 From 7215e9375694dbb2306082b516d824b9335fa409 Mon Sep 17 00:00:00 2001 From: Andrei Botila Date: Fri, 28 Feb 2025 17:43:20 +0200 Subject: [PATCH 14/16] net: phy: nxp-c45-tja11xx: add support for TJA1121 Add support for TJA1121 which is based on TJA1120 but with additional MACsec IP. Signed-off-by: Andrei Botila Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250228154320.2979000-3-andrei.botila@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/Kconfig | 2 +- drivers/net/phy/nxp-c45-tja11xx.c | 40 ++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 41c15a2c2037..d29f9f7fd2e1 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -328,7 +328,7 @@ config NXP_C45_TJA11XX_PHY depends on MACSEC || !MACSEC help Enable support for NXP C45 TJA11XX PHYs. - Currently supports the TJA1103, TJA1104 and TJA1120 PHYs. + Currently supports the TJA1103, TJA1104, TJA1120 and TJA1121 PHYs. config NXP_TJA11XX_PHY tristate "NXP TJA11xx PHYs support" diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 4013a17c205a..63945fe58227 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -22,6 +22,7 @@ #define PHY_ID_MASK GENMASK(31, 4) /* Same id: TJA1103, TJA1104 */ #define PHY_ID_TJA_1103 0x001BB010 +/* Same id: TJA1120, TJA1121 */ #define PHY_ID_TJA_1120 0x001BB031 #define VEND1_DEVICE_CONTROL 0x0040 @@ -1914,6 +1915,18 @@ static int tja1104_match_phy_device(struct phy_device *phydev) nxp_c45_macsec_ability(phydev); } +static int tja1120_match_phy_device(struct phy_device *phydev) +{ + return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) && + !nxp_c45_macsec_ability(phydev); +} + +static int tja1121_match_phy_device(struct phy_device *phydev) +{ + return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, PHY_ID_MASK) && + nxp_c45_macsec_ability(phydev); +} + static const struct nxp_c45_regmap tja1120_regmap = { .vend1_ptp_clk_period = 0x1020, .vend1_event_msg_filt = 0x9010, @@ -2032,7 +2045,6 @@ static struct phy_driver nxp_c45_driver[] = { .match_phy_device = tja1104_match_phy_device, }, { - PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), .name = "NXP C45 TJA1120", .get_features = nxp_c45_get_features, .driver_data = &tja1120_phy_data, @@ -2055,6 +2067,32 @@ static struct phy_driver nxp_c45_driver[] = { .get_sqi = nxp_c45_get_sqi, .get_sqi_max = nxp_c45_get_sqi_max, .remove = nxp_c45_remove, + .match_phy_device = tja1120_match_phy_device, + }, + { + .name = "NXP C45 TJA1121", + .get_features = nxp_c45_get_features, + .driver_data = &tja1120_phy_data, + .probe = nxp_c45_probe, + .soft_reset = nxp_c45_soft_reset, + .config_aneg = genphy_c45_config_aneg, + .config_init = nxp_c45_config_init, + .config_intr = tja1120_config_intr, + .handle_interrupt = nxp_c45_handle_interrupt, + .read_status = genphy_c45_read_status, + .link_change_notify = tja1120_link_change_notify, + .suspend = genphy_c45_pma_suspend, + .resume = genphy_c45_pma_resume, + .get_sset_count = nxp_c45_get_sset_count, + .get_strings = nxp_c45_get_strings, + .get_stats = nxp_c45_get_stats, + .cable_test_start = nxp_c45_cable_test_start, + .cable_test_get_status = nxp_c45_cable_test_get_status, + .set_loopback = genphy_c45_loopback, + .get_sqi = nxp_c45_get_sqi, + .get_sqi_max = nxp_c45_get_sqi_max, + .remove = nxp_c45_remove, + .match_phy_device = tja1121_match_phy_device, }, }; -- 2.51.0 From e4c4522390c90f9ef2d3491e9eb5f19a6fac00e2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=2E=20Neusch=C3=A4fer?= Date: Fri, 28 Feb 2025 18:32:50 +0100 Subject: [PATCH 15/16] dt-bindings: net: Convert fsl,gianfar-{mdio,tbi} to YAML MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Move the information related to the Freescale Gianfar (TSEC) MDIO bus and the Ten-Bit Interface (TBI) from fsl-tsec-phy.txt to a new binding file in YAML format, fsl,gianfar-mdio.yaml. Signed-off-by: J. Neuschäfer Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250228-gianfar-yaml-v2-1-6beeefbd4818@posteo.net Signed-off-by: Jakub Kicinski --- .../bindings/net/fsl,gianfar-mdio.yaml | 113 ++++++++++++++++++ .../devicetree/bindings/net/fsl-tsec-phy.txt | 41 +------ 2 files changed, 115 insertions(+), 39 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml diff --git a/Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml b/Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml new file mode 100644 index 000000000000..22369771c136 --- /dev/null +++ b/Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/fsl,gianfar-mdio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale Gianfar (TSEC) MDIO Device + +description: + This binding describes the MDIO is a bus to which the PHY devices are + connected. For each device that exists on this bus, a child node should be + created. + + As of this writing, every TSEC is associated with an internal Ten-Bit + Interface (TBI) PHY. This PHY is accessed through the local MDIO bus. These + buses are defined similarly to the mdio buses, except they are compatible + with "fsl,gianfar-tbi". The TBI PHYs underneath them are similar to normal + PHYs, but the reg property is considered instructive, rather than + descriptive. The reg property should be chosen so it doesn't interfere with + other PHYs on the bus. + +maintainers: + - J. Neuschäfer + +# This is needed to distinguish gianfar.yaml and gianfar-mdio.yaml, because +# both use compatible = "gianfar" (with different device_type values) +select: + oneOf: + - properties: + compatible: + contains: + const: gianfar + device_type: + const: mdio + required: + - device_type + + - properties: + compatible: + contains: + enum: + - fsl,gianfar-tbi + - fsl,gianfar-mdio + - fsl,etsec2-tbi + - fsl,etsec2-mdio + - fsl,ucc-mdio + - ucc_geth_phy + + required: + - compatible + +properties: + compatible: + enum: + - fsl,gianfar-tbi + - fsl,gianfar-mdio + - fsl,etsec2-tbi + - fsl,etsec2-mdio + - fsl,ucc-mdio + - gianfar + - ucc_geth_phy + + reg: + minItems: 1 + items: + - description: + Offset and length of the register set for the device + + - description: + Optionally, the offset and length of the TBIPA register (TBI PHY + address register). If TBIPA register is not specified, the driver + will attempt to infer it from the register set specified (your + mileage may vary). + + device_type: + const: mdio + +required: + - reg + - "#address-cells" + - "#size-cells" + +allOf: + - $ref: mdio.yaml# + + - if: + properties: + compatible: + contains: + const: ucc_geth_phy + then: + required: + - device_type + +unevaluatedProperties: false + +examples: + - | + soc { + #address-cells = <1>; + #size-cells = <1>; + + mdio@24520 { + reg = <0x24520 0x20>; + compatible = "fsl,gianfar-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + reg = <0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt b/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt index 9c9668c1b6a2..0e55e0af7d6f 100644 --- a/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt +++ b/Documentation/devicetree/bindings/net/fsl-tsec-phy.txt @@ -1,47 +1,10 @@ * MDIO IO device -The MDIO is a bus to which the PHY devices are connected. For each -device that exists on this bus, a child node should be created. See -the definition of the PHY node in booting-without-of.txt for an example -of how to define a PHY. - -Required properties: - - reg : Offset and length of the register set for the device, and optionally - the offset and length of the TBIPA register (TBI PHY address - register). If TBIPA register is not specified, the driver will - attempt to infer it from the register set specified (your mileage may - vary). - - compatible : Should define the compatible device type for the - mdio. Currently supported strings/devices are: - - "fsl,gianfar-tbi" - - "fsl,gianfar-mdio" - - "fsl,etsec2-tbi" - - "fsl,etsec2-mdio" - - "fsl,ucc-mdio" - - "fsl,fman-mdio" - When device_type is "mdio", the following strings are also considered: - - "gianfar" - - "ucc_geth_phy" - -Example: - - mdio@24520 { - reg = <24520 20>; - compatible = "fsl,gianfar-mdio"; - - ethernet-phy@0 { - ...... - }; - }; +Refer to Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml * TBI Internal MDIO bus -As of this writing, every tsec is associated with an internal TBI PHY. -This PHY is accessed through the local MDIO bus. These buses are defined -similarly to the mdio buses, except they are compatible with "fsl,gianfar-tbi". -The TBI PHYs underneath them are similar to normal PHYs, but the reg property -is considered instructive, rather than descriptive. The reg property should -be chosen so it doesn't interfere with other PHYs on the bus. +Refer to Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml * Gianfar-compatible ethernet nodes -- 2.51.0 From 0386e29e60bdb0985f4bdf1c4a7fadebdef724be Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=2E=20Neusch=C3=A4fer?= Date: Fri, 28 Feb 2025 18:32:51 +0100 Subject: [PATCH 16/16] dt-bindings: net: fsl,gianfar-mdio: Update information about TBI MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When this binding was originally written, all known TSEC Ethernet controllers had a Ten-Bit Interface (TBI). However, some datasheets such as for the MPC8315E suggest that this is not universally true: The eTSECs do not support TBI, GMII, and FIFO operating modes, so all references to these interfaces and features should be ignored for this device. Acked-by: Rob Herring (Arm) Signed-off-by: J. Neuschäfer Link: https://patch.msgid.link/20250228-gianfar-yaml-v2-2-6beeefbd4818@posteo.net Signed-off-by: Jakub Kicinski --- .../devicetree/bindings/net/fsl,gianfar-mdio.yaml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml b/Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml index 22369771c136..03c819bc701b 100644 --- a/Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml +++ b/Documentation/devicetree/bindings/net/fsl,gianfar-mdio.yaml @@ -11,13 +11,12 @@ description: connected. For each device that exists on this bus, a child node should be created. - As of this writing, every TSEC is associated with an internal Ten-Bit - Interface (TBI) PHY. This PHY is accessed through the local MDIO bus. These - buses are defined similarly to the mdio buses, except they are compatible - with "fsl,gianfar-tbi". The TBI PHYs underneath them are similar to normal - PHYs, but the reg property is considered instructive, rather than - descriptive. The reg property should be chosen so it doesn't interfere with - other PHYs on the bus. + Some TSECs are associated with an internal Ten-Bit Interface (TBI) PHY. This + PHY is accessed through the local MDIO bus. These buses are defined similarly + to the mdio buses, except they are compatible with "fsl,gianfar-tbi". The TBI + PHYs underneath them are similar to normal PHYs, but the reg property is + considered instructive, rather than descriptive. The reg property should be + chosen so it doesn't interfere with other PHYs on the bus. maintainers: - J. Neuschäfer -- 2.51.0