From nobody Sun May 24 22:34:04 2026 Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C5A032E72F for ; Wed, 20 May 2026 20:03:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779307423; cv=none; b=lyw9l27cqz10HJPenMi6SlqmJOXYXTXzhhZMUVhwg3u23+UtFmRzQFsEsSviwa7ZIFAcJE/yQTZXKv0Rq0dzp2UzdeA7zNv+JIpcCy2pZQaNaMr+a2Ze1RjIh8bIFl4Li2Wk810FzhAytZxgTq+2EVjeF5yHIENBYlTV8vLjH8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779307423; c=relaxed/simple; bh=w5MLQIaRpVU5SwkEFl0ywM8vQ/Epne164k8OfCiap98=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZRYzt5eZcIfak+CivcmRuudUmdgb/dZ0r+fvNCnnwSAxfHxlrUXBZfiMhKaP/H1k1+VsERPtB3ILfmqxBiqvW314dieP9huZxSYDKvvESj9AYzGJTgbpOKKHhhSHmYCxVycWWuatOJsIxM3W2R1WJRq2mfH/iJg4N2N0MC9XVWQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Md6ZBBi6; arc=none smtp.client-ip=209.85.160.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Md6ZBBi6" Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-5164dafcf97so53622161cf.2 for ; Wed, 20 May 2026 13:03:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779307421; x=1779912221; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=PJFwvFMqSeGHKF7YuuKfX7SCPCAWVzw/mYZh++eDvbM=; b=Md6ZBBi6L891kRa3CYITpsH0nbL6nj2kyNEb29KVvms2HET7uyFGQyVCyFLfkbcovr kB1Zlf98XxoHyKoKIoRaSbMdGjgnKZ6cm02BkNGVkRF27jretlWqPgxhasJmI9DVDGEB hrDgErotK1SZ3f69OV5iJp/Ku6Zsnh+hNgUB/syoEZkTj/wImRB6vtkLHTcZWM/CrKe7 RC6f9uhBBn7D4vVizGoABok9Z1j8U1GZPIKv/QM6T1B1tBOJR7pzcGVKkzcTq6DDmFR3 L8cy6TQuiPiIMnEg8FeJki9MNmbnPn6EPKm8V6LiRgGYRVLgybrw5iH7slgEhPTHdu8T EDRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779307421; x=1779912221; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=PJFwvFMqSeGHKF7YuuKfX7SCPCAWVzw/mYZh++eDvbM=; b=YYC/GZAilGzPwVmY5j1sHUnrOAjw+tjcLJS/Hxi59LQFTWQXaG/ijibrOcMhVqYZOz ybMsCUlIKAZsDeNYpqeUSykCiCiWs2eRiSLspvozEGj9SUqvlv/AKwzD5Wc+eXCTKc2E XZK42LLpx7Bg6CMYV4tFgEYGkqnwLcTkLc4q+/af9euvyVxQ3v9+NGPWP6u2bg8pBSMq uoe57BDyIQxIyXJifO43A0gN7pXw2AUoMIHSRyCILZZBXDjFE/wYyFiH+KOI4uogmRJg 87SxClv+QxBf5CtkpyMxz26jxwxk4QgeyheZh1pn6xMrhGDJkPmnm/416c0gcPZ/v0FA 2Dgg== X-Forwarded-Encrypted: i=1; AFNElJ9PvMYlZdwdCt6U3OVMOqFr7Gb5iCPNdi9symlntJ/B2626qwA0GY5KgpzGLeRk/N1twh4L9jN2CaEVqgI=@vger.kernel.org X-Gm-Message-State: AOJu0YyoWtncJtHqdctKfUJsvYDiFTw7NF8044ltA+2joSxSnL6B6nW/ jrCoTYX6NUBWl4aXTPGlbibw/I3TERt3njc8DRyrhOW8UEZjgjU4b6b6 X-Gm-Gg: Acq92OG9NgYpBxUzvvSV8PtWeFzOpqZiYsUmKIxfv+A+FaKMRhEPTr26hj0gKrjovxy HfKBSpj6ZpcwIIQlYZTqWUdk70+DBXH1d+Y0w4wo8mFXuTjeRp1m2hjooAiYsDNotsEYMwTHwCr iuw7IgfQxKSayQUh+omsa4dKhts/pDN3a27FTX0X/PSjIpybl+W1m9GhOG3dYVf8W4I4ZFlUz1f ZdRQiuS2DKBt8r2tGNqICZmH02E0cIN0axYTtqtohckWQFrGCeJQ6hIBZk4tnIi4V2W0Nj0pjEL k5zg8iNDxWE2x1Uhuju1dmJB9ZJwyMdDyCM5BFEqckx0qtoLgUMNFBzm8hHgb5lLQuGGnRIpuHK 3KkIZn35x8qhi3tvmNJ1LSBLhnimJlnIpF59veejaaRQ2ws/xKjeApI4ue9j6kOmJQbGP1x+Tr8 hRhUehLbrXCMXeOo5HRNysslwDT/yRbGBcXSrjuy6Fa5zGulHSvwmJvKqsxe98TijLvco= X-Received: by 2002:a05:622a:4d09:b0:509:2527:d789 with SMTP id d75a77b69052e-51659fde5ecmr365261451cf.6.1779307421006; Wed, 20 May 2026 13:03:41 -0700 (PDT) Received: from PF5YBGDS.localdomain ([163.114.130.1]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-516514e0b91sm188849301cf.15.2026.05.20.13.03.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 May 2026 13:03:40 -0700 (PDT) From: mike.marciniszyn@gmail.com To: Lee Jones , Pavel Machek , Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Russell King , Daniel Golle , Kees Cook , Simon Horman , Dimitri Daskalakis , Jacob Keller , Lee Trager , Mohsin Bashir , Alok Tiwari , Chengfeng Ye , Andy Shevchenko , Andrew Lunn Cc: mike.marciniszyn@gmail.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH net-next 1/3] leds: trigger: netdev: Extend speeds up to 100G Date: Wed, 20 May 2026 16:03:35 -0400 Message-ID: <20260520200337.204431-2-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260520200337.204431-1-mike.marciniszyn@gmail.com> References: <20260520200337.204431-1-mike.marciniszyn@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" Add 25G, 40G, 50G, and 100G as available speeds to the netdev LED trigger. Signed-off-by: Mike Marciniszyn (Meta) Reviewed-by: Andrew Lunn --- drivers/leds/trigger/ledtrig-netdev.c | 46 ++++++++++++++++++++++++++- include/linux/leds.h | 4 +++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/l= edtrig-netdev.c index 12cb3311ea22..3c758a4cbaec 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -128,6 +128,22 @@ static void set_baseline_state(struct led_netdev_data = *trigger_data) trigger_data->link_speed =3D=3D SPEED_10000) blink_on =3D true; =20 + if (test_bit(TRIGGER_NETDEV_LINK_25000, &trigger_data->mode) && + trigger_data->link_speed =3D=3D SPEED_25000) + blink_on =3D true; + + if (test_bit(TRIGGER_NETDEV_LINK_40000, &trigger_data->mode) && + trigger_data->link_speed =3D=3D SPEED_40000) + blink_on =3D true; + + if (test_bit(TRIGGER_NETDEV_LINK_50000, &trigger_data->mode) && + trigger_data->link_speed =3D=3D SPEED_50000) + blink_on =3D true; + + if (test_bit(TRIGGER_NETDEV_LINK_100000, &trigger_data->mode) && + trigger_data->link_speed =3D=3D SPEED_100000) + blink_on =3D true; + if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && trigger_data->duplex =3D=3D DUPLEX_HALF) blink_on =3D true; @@ -337,6 +353,10 @@ static ssize_t netdev_led_attr_show(struct device *dev= , char *buf, case TRIGGER_NETDEV_LINK_2500: case TRIGGER_NETDEV_LINK_5000: case TRIGGER_NETDEV_LINK_10000: + case TRIGGER_NETDEV_LINK_25000: + case TRIGGER_NETDEV_LINK_40000: + case TRIGGER_NETDEV_LINK_50000: + case TRIGGER_NETDEV_LINK_100000: case TRIGGER_NETDEV_HALF_DUPLEX: case TRIGGER_NETDEV_FULL_DUPLEX: case TRIGGER_NETDEV_TX: @@ -373,6 +393,10 @@ static ssize_t netdev_led_attr_store(struct device *de= v, const char *buf, case TRIGGER_NETDEV_LINK_2500: case TRIGGER_NETDEV_LINK_5000: case TRIGGER_NETDEV_LINK_10000: + case TRIGGER_NETDEV_LINK_25000: + case TRIGGER_NETDEV_LINK_40000: + case TRIGGER_NETDEV_LINK_50000: + case TRIGGER_NETDEV_LINK_100000: case TRIGGER_NETDEV_HALF_DUPLEX: case TRIGGER_NETDEV_FULL_DUPLEX: case TRIGGER_NETDEV_TX: @@ -396,7 +420,11 @@ static ssize_t netdev_led_attr_store(struct device *de= v, const char *buf, test_bit(TRIGGER_NETDEV_LINK_1000, &mode) || test_bit(TRIGGER_NETDEV_LINK_2500, &mode) || test_bit(TRIGGER_NETDEV_LINK_5000, &mode) || - test_bit(TRIGGER_NETDEV_LINK_10000, &mode))) + test_bit(TRIGGER_NETDEV_LINK_10000, &mode) || + test_bit(TRIGGER_NETDEV_LINK_25000, &mode) || + test_bit(TRIGGER_NETDEV_LINK_40000, &mode) || + test_bit(TRIGGER_NETDEV_LINK_50000, &mode) || + test_bit(TRIGGER_NETDEV_LINK_100000, &mode))) return -EINVAL; =20 cancel_delayed_work_sync(&trigger_data->work); @@ -433,6 +461,10 @@ DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1= 000); DEFINE_NETDEV_TRIGGER(link_2500, TRIGGER_NETDEV_LINK_2500); DEFINE_NETDEV_TRIGGER(link_5000, TRIGGER_NETDEV_LINK_5000); DEFINE_NETDEV_TRIGGER(link_10000, TRIGGER_NETDEV_LINK_10000); +DEFINE_NETDEV_TRIGGER(link_25000, TRIGGER_NETDEV_LINK_25000); +DEFINE_NETDEV_TRIGGER(link_40000, TRIGGER_NETDEV_LINK_40000); +DEFINE_NETDEV_TRIGGER(link_50000, TRIGGER_NETDEV_LINK_50000); +DEFINE_NETDEV_TRIGGER(link_100000, TRIGGER_NETDEV_LINK_100000); DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); @@ -521,6 +553,10 @@ static umode_t netdev_trig_link_speed_visible(struct k= object *kobj, CHECK_LINK_MODE_ATTR(2500); CHECK_LINK_MODE_ATTR(5000); CHECK_LINK_MODE_ATTR(10000); + CHECK_LINK_MODE_ATTR(25000); + CHECK_LINK_MODE_ATTR(40000); + CHECK_LINK_MODE_ATTR(50000); + CHECK_LINK_MODE_ATTR(100000); } =20 return 0; @@ -533,6 +569,10 @@ static struct attribute *netdev_trig_link_speed_attrs[= ] =3D { &dev_attr_link_2500.attr, &dev_attr_link_5000.attr, &dev_attr_link_10000.attr, + &dev_attr_link_25000.attr, + &dev_attr_link_40000.attr, + &dev_attr_link_50000.attr, + &dev_attr_link_100000.attr, NULL }; =20 @@ -668,6 +708,10 @@ static void netdev_trig_work(struct work_struct *work) test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) || test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) || test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_25000, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_40000, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_50000, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_100000, &trigger_data->mode) || test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); interval =3D jiffies_to_msecs( diff --git a/include/linux/leds.h b/include/linux/leds.h index b16b803cc1ac..bf31c246d9e2 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -607,6 +607,10 @@ enum led_trigger_netdev_modes { TRIGGER_NETDEV_LINK_2500, TRIGGER_NETDEV_LINK_5000, TRIGGER_NETDEV_LINK_10000, + TRIGGER_NETDEV_LINK_25000, + TRIGGER_NETDEV_LINK_40000, + TRIGGER_NETDEV_LINK_50000, + TRIGGER_NETDEV_LINK_100000, TRIGGER_NETDEV_HALF_DUPLEX, TRIGGER_NETDEV_FULL_DUPLEX, TRIGGER_NETDEV_TX, --=20 2.43.0 From nobody Sun May 24 22:34:04 2026 Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 196DD346E7D for ; Wed, 20 May 2026 20:03:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779307425; cv=none; b=pE/sM02Pyi6tzqLnO7kNtkXz9DgA1UuJ0X0okbeLP2e8yCY91fbL3l2jS/5tWQfqQF5INl+dTPbuEfwqKQ03/vnBdoKoCovo4pfiUlA4VteqlmIkr+xymFMivV9hirykN34L+osNumAp8Sjk8w3HWpp7M1OJuCzpV+zZ8Xfnk4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779307425; c=relaxed/simple; bh=Xvv5fQ5F5xIWtEaWElIAcf+23Bvf0pXPnm8EdudGugA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dswh8/UwH2ucfHFjCgNvcx9WMpqiFp9WgjzJqLQr4LSTKB0OMuU2fhdjeMYImk3s7BjSBy9iG3he+MFsb1oWmVerCSlv+s+bWNyR/n56Zq5KD33lRNAuIqP+NXHqyb8AJJialVUbSZxDWJDoV10jCQ7P0IrAawJLhp8TidYbASs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Tu9jzpTC; arc=none smtp.client-ip=209.85.222.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Tu9jzpTC" Received: by mail-qk1-f171.google.com with SMTP id af79cd13be357-90f850473f9so555578285a.3 for ; Wed, 20 May 2026 13:03:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779307423; x=1779912223; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8pPtDRaFJhpJpi9KrC1PwJKKtOYZtFzoBHFHqlj56RU=; b=Tu9jzpTCpVUUoJ2IHa+AOCrOEK2khueqdyh8456OVxgl9CnlLHpAVWtg7SQmuv8yAY brFTb5lHB/7KRCQ9hZVHlCNnhHnIa18EqghllofejEoi9MKiOkjQ6X/S8rJ6YRTbhW4l Mm2eOUqgMrXDrrL2r/quvFaux6JCmxxHUUob97km6GDbNT+d12cLCRNXZy3FZDRjB6aM xzBOzH4jp4gGRKDOnMm+zGDEbzfNGrrKO23i0nWPePaAt0eYHaRVlQcQHKdHjN36o2nh s9LFDdpAFssZ8X9wPwBpIUlgzq/DT6jfIJglWLm7xgAXwAdQRTy7wHxmq1eeZtFfnxi0 9NdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779307423; x=1779912223; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=8pPtDRaFJhpJpi9KrC1PwJKKtOYZtFzoBHFHqlj56RU=; b=n3Zga4Y98132jL7R/+SwyEMleSEDXSvORgX28kdpFySCKeQ/6rfw3h9pZ3EpSbC6RT xFDWOZBA95uKqwgyPYiu0OcNlket3cDdEd/Rr3Rl4ny9Yw6JtmLFL6lyE039SbdasUf4 bk1Htl3gpvZbJbHqY14hPyUGdc+7IQXvaBhZRQVV2q83Skcv3h7xc+HUzGyMZlNpduDo HfZODbm0JAS3oZALwcLYvpOh2ZQbidL5S0TlGX1BenclghiRb9IMIw/2kffZkRhtN4pg /wHjdiF93DzmiVHf6rMkQVclS1eN2SvGtfR37whI0OjdQN8by0uCIcA4vwPL0ZvwbrsB 66TQ== X-Forwarded-Encrypted: i=1; AFNElJ8/4lT5oTYK0oFn8DcW3u8SGWB4zlU9EOS5Q38VuxoTSpw4hEsqIwJhtu20nVG/JolAppGlJdFHu0HjNGk=@vger.kernel.org X-Gm-Message-State: AOJu0YxPcCEELIt1Q6XaxE5O0zA2DOY5SU71eSYJI1HU0CvlrRjDGkGp qxLtKlb4tAlSg0aSY4rPpR543XXda+u6+/6vBqtNtsFbRmlx19SVCnp6 X-Gm-Gg: Acq92OFyJVUizj7N95bq1wzqmS/bClhRb3ct9qANBNvNzFAEpJDyTBkOUYlXoNYAVrm raLlBhTqmKxpuiYH9Ow1CVLmcqKTFNM5N50T/FD+XPUdjgW0kX4Vjqg4Q6pclI0I+LBSmcaqL79 PZkvboDK6xJjHo0gDI2hBHtY5bnEhlxpK0SKmX5AfX+2MYApxjqOSXhmidzbq4FGK/VZRe7zFk5 QjaYzSDWYDxs8vkGpZnD9o5g+x76RZaiwq3gh4+WNRQ5914+PW4m+qkoMHrzWaQuuGKTg4pDE9x hQdpJ0R06Mu28Bw2OYpHqn1rgIxcTy52IYn60l1WQAenUXVgQ7s36ipNSQsvYv4npBvfJ27qBO/ D+KGBGsAaw6aEPCNX+ro1m1E47YtxqFBzJyqSpTs3ACzGplVrXPSvBdptS/0/9yXXCAGvf5rYlk iLnst+OQblOlHCkRk6QvawAXkfBotTYsmTec1H/+Vmj/EsFDMPDFZ9epZq X-Received: by 2002:a05:622a:d1:b0:509:1b76:e9b2 with SMTP id d75a77b69052e-5165a276812mr354941421cf.55.1779307423016; Wed, 20 May 2026 13:03:43 -0700 (PDT) Received: from PF5YBGDS.localdomain ([163.114.130.1]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-516514e0b91sm188849301cf.15.2026.05.20.13.03.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 May 2026 13:03:42 -0700 (PDT) From: mike.marciniszyn@gmail.com To: Lee Jones , Pavel Machek , Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Russell King , Daniel Golle , Kees Cook , Simon Horman , Dimitri Daskalakis , Jacob Keller , Lee Trager , Mohsin Bashir , Alok Tiwari , Chengfeng Ye , Andy Shevchenko , Andrew Lunn Cc: mike.marciniszyn@gmail.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH net-next 2/3] net: eth: fbnic: Store max_speed from firmware dialog Date: Wed, 20 May 2026 16:03:36 -0400 Message-ID: <20260520200337.204431-3-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260520200337.204431-1-mike.marciniszyn@gmail.com> References: <20260520200337.204431-1-mike.marciniszyn@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" The OCP spec required LED signalling to signal the difference between both below and at max speed capability. The firmware init dialog already contains that attribute so store it to support follow-on patches. Signed-off-by: Mike Marciniszyn (Meta) --- drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 3 +++ drivers/net/ethernet/meta/fbnic/fbnic_fw.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ether= net/meta/fbnic/fbnic_fw.c index 0c6812fcf185..59015769ca28 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c @@ -561,6 +561,7 @@ static const struct fbnic_tlv_index fbnic_fw_cap_resp_i= ndex[] =3D { FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_ACTIVE_FW_SLOT), FBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_VERSION_COMMIT_STR, FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE), + FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_FW_MAX_LINK_SPEED), FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_BMC_ALL_MULTI), FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_FW_LINK_SPEED), FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_FW_LINK_FEC), @@ -667,6 +668,8 @@ static int fbnic_fw_parse_cap_resp(void *opaque, struct= fbnic_tlv_msg **results) =20 fbd->fw_cap.active_slot =3D fta_get_uint(results, FBNIC_FW_CAP_RESP_ACTIVE_FW_SLOT); + fbd->fw_cap.max_link_speed =3D + fta_get_uint(results, FBNIC_FW_CAP_RESP_FW_MAX_LINK_SPEED); fbd->fw_cap.link_speed =3D fta_get_uint(results, FBNIC_FW_CAP_RESP_FW_LINK_SPEED); fbd->fw_cap.link_fec =3D diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ether= net/meta/fbnic/fbnic_fw.h index d84723e4cfa3..55c2ebc223d0 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h @@ -58,6 +58,7 @@ struct fbnic_fw_cap { u8 need_bmc_macda_sync : 1; u8 all_multi : 1; u8 link_speed; + u8 max_link_speed; u8 link_fec; u32 anti_rollback_version; }; @@ -241,6 +242,8 @@ enum { FBNIC_FW_CAP_RESP_STORED_CMRT_COMMIT_STR =3D 0x10, FBNIC_FW_CAP_RESP_UEFI_VERSION =3D 0x11, FBNIC_FW_CAP_RESP_UEFI_COMMIT_STR =3D 0x12, + FBNIC_FW_CAP_RESP_FW_MAX_LINK_SPEED =3D 0x13, + /* 0x14 reserved */ FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION =3D 0x15, FBNIC_FW_CAP_RESP_MSG_MAX }; --=20 2.43.0 From nobody Sun May 24 22:34:04 2026 Received: from mail-qt1-f178.google.com (mail-qt1-f178.google.com [209.85.160.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B922F362130 for ; Wed, 20 May 2026 20:03:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779307428; cv=none; b=YcUrntZIRuar/ht9uLon/gVGHj+7gOPd4KArhqoej7w1Xmqchg5iy8ko8zdjGIO4PQW/7jak5pAly2JAxNRNsp2VhW0kk0P9x/TO0V7W3TWbVEEeEQioqTj8v1gK2UIhEP6tZXdOWVnKfoBVJ/FeKMj5Twd5Il1BSpalbhJyvSI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779307428; c=relaxed/simple; bh=6cvUJBRsRmETKHLO52FmOFc//tiyQIlkClqq+i0qF9Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oz066V0GGRsRh1tl+Y7GY3K3Mq/FRwppPbnyVvD7NK3d8gkB0ai4AIY7WgvEIIqfgzEItpPePmnX1cvM96QOJnFAWC6DvvuV85vPy+Ul2EVj0WJnWU/Ijb3OyFgBKHn96Wg4z06aVopDg3JXmxxZPSdCyQ5tAOEFh1w5HBVDEWw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kjJ0gNnJ; arc=none smtp.client-ip=209.85.160.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kjJ0gNnJ" Received: by mail-qt1-f178.google.com with SMTP id d75a77b69052e-516389a9b70so58018771cf.3 for ; Wed, 20 May 2026 13:03:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779307425; x=1779912225; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1N4UB0YVLf3dldz+nPe+MFHXrscyQbdsHGnb1vXEfI4=; b=kjJ0gNnJT9h/Oubu9xgbGM8aa77fmvEU7lDhFGoenjhH7+DiFhFovu3K6xdPjcwhzh zVhqh7K00lzC2Z+jef4GJ4EqaZrOKUuA0pZdUH0yv7mB2XxM6VZz2w9E8j5STNRbWYWV 2bGJqHqsVsFiI13sWRBvNb+SUWpNJr3/IukTmxSuUonmz/sQC7WrZurVM5yWFwZtCuiL /+CFhnNH36bmceHZ9/zSGZW9cBdwQPNla9BZto/k74v8/6h6L5atWTis/lOQJJQNAoLk EMGdqWpNb4vSJcx+ouMmyen5FJBBMeIqXP76xxL7z/nJUH2/7etd4fCiX0LwQ6f1395m xIsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779307425; x=1779912225; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=1N4UB0YVLf3dldz+nPe+MFHXrscyQbdsHGnb1vXEfI4=; b=ndammUDvmMQlGBHRNjO0UfvjVCONSVqSCDQ0xcBYh9yq00KIyNYC1IoYMRT81XdLtr S/bBD255PCVRnmFWqPD+VLz9CUAvZHK5wuTGXZ319a1DTwxucxV/2UdkUHdQuKFRs+hz 8DxIQ25O0r8VS2/g7fas985R7Bbzgxg+dAodq3gBthYmgIYbG3icWyRh7Q3nodObrcab FM2DAyeKVolgbQolZodB0RG9w39QxhEYYSIt8cd+JS5J5SD7UAkQb/m8MYADkW+2eeaA 6VizqjGCMgtZQGwTQEoCa0vxHSyAQjb6l9p1lHE4bXZGAgvS3okMSqCEQKkNeSaSGogs IgBA== X-Forwarded-Encrypted: i=1; AFNElJ/Z0zph7psNW2PuKqyZKsxHH08wgKkTd7q0eYkx9k8IaBRRekwO3Y3guhXgYKvTvK1OJEqopHlRefH5s2A=@vger.kernel.org X-Gm-Message-State: AOJu0Yz+KzHru6mDDPFezghY/S4loodSJs09dsilCQraYa3eueaJ8Gd9 t4Id/GLGTI7+66TRCa9hMN8LqIrMSAxfYahPi42LveC6bm4BThEiX1ya X-Gm-Gg: Acq92OGx5G12pKnFgKBgFkNxcbjXtMOLDiPX02iU7LtvwvlsD958+3YDqkfdyzz4owk iV0UvOQ4rmmZN4Z4ie0SgeG65KtSutVuBvOuC4ov3ZXxCEQJQdNjKH0CaMuCe8qapzU2tMX6F/6 sKVo3/8KPYJnW8dpgMYxi/f9JL2U136XgZo2LgcYwq2YcA6kFJO+gRPsWxKlj3l+oh6IW65/tqd aap7EwTYqznT4FAdX2zGXRwpO3DCC+/fGLxFEpsxGSFg+w44f1V1HhF23oR0zRVjcYmJ0z/N54g JFpxup3TjZomFog3WCk+zSVxf0jb7BGFgT0McYHkqRQkFrdm+v+S0vzUBPHq9KyfjtuaL9K5ySP IteA36r4ocF9CzjLxdrdvct0N9M9Ob993DawDRXVz2PdrJulg2ki2fVcTOMU1mWf3Zb9LdtLI/H 97IPzCVS/+vXTukKz+9Tow6NZU/z/V92xM8a2XuBJUhHgGMOzdqgRvV4GR X-Received: by 2002:ac8:5f4b:0:b0:510:2506:1ba9 with SMTP id d75a77b69052e-5165a1f326bmr334535821cf.49.1779307424327; Wed, 20 May 2026 13:03:44 -0700 (PDT) Received: from PF5YBGDS.localdomain ([163.114.130.1]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-516514e0b91sm188849301cf.15.2026.05.20.13.03.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 May 2026 13:03:43 -0700 (PDT) From: mike.marciniszyn@gmail.com To: Lee Jones , Pavel Machek , Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Russell King , Daniel Golle , Kees Cook , Simon Horman , Dimitri Daskalakis , Jacob Keller , Lee Trager , Mohsin Bashir , Alok Tiwari , Chengfeng Ye , Andy Shevchenko , Andrew Lunn Cc: mike.marciniszyn@gmail.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH net-next 3/3] net: eth: fbnic: Add led support Date: Wed, 20 May 2026 16:03:37 -0400 Message-ID: <20260520200337.204431-4-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260520200337.204431-1-mike.marciniszyn@gmail.com> References: <20260520200337.204431-1-mike.marciniszyn@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" This patch adds the LED support for fbnic and adds the user /sys/class/leds interfaces based on CONFIG_FBNIC_LEDS. Signed-off-by: Mike Marciniszyn (Meta) --- drivers/net/ethernet/meta/Kconfig | 8 + drivers/net/ethernet/meta/fbnic/Makefile | 2 + drivers/net/ethernet/meta/fbnic/fbnic.h | 13 + drivers/net/ethernet/meta/fbnic/fbnic_csr.h | 15 ++ .../net/ethernet/meta/fbnic/fbnic_devlink.c | 4 + .../net/ethernet/meta/fbnic/fbnic_ethtool.c | 59 +++++ drivers/net/ethernet/meta/fbnic/fbnic_led.c | 228 +++++++++++++++++ drivers/net/ethernet/meta/fbnic/fbnic_mac.c | 239 ++++++++++++++++++ drivers/net/ethernet/meta/fbnic/fbnic_mac.h | 62 +++++ drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 8 + .../net/ethernet/meta/fbnic/fbnic_phylink.c | 2 + 11 files changed, 640 insertions(+) create mode 100644 drivers/net/ethernet/meta/fbnic/fbnic_led.c diff --git a/drivers/net/ethernet/meta/Kconfig b/drivers/net/ethernet/meta/= Kconfig index ca5c7ac2a5bc..a8ca2aaf798a 100644 --- a/drivers/net/ethernet/meta/Kconfig +++ b/drivers/net/ethernet/meta/Kconfig @@ -35,4 +35,12 @@ config FBNIC To compile this driver as a module, choose M here. The module will be called fbnic. MSI-X interrupt support is required. =20 +config FBNIC_LEDS + def_bool LEDS_TRIGGER_NETDEV + depends on FBNIC && LEDS_CLASS + depends on LEDS_CLASS=3Dy || FBNIC=3Dm + help + Optional support for controlling the NIC LEDs with the netdev + LED trigger. + endif # NET_VENDOR_META diff --git a/drivers/net/ethernet/meta/fbnic/Makefile b/drivers/net/etherne= t/meta/fbnic/Makefile index 72c41af65364..7f3b70a1f444 100644 --- a/drivers/net/ethernet/meta/fbnic/Makefile +++ b/drivers/net/ethernet/meta/fbnic/Makefile @@ -26,3 +26,5 @@ fbnic-y :=3D fbnic_csr.o \ fbnic_tlv.o \ fbnic_txrx.o \ # End of objects + +fbnic-$(CONFIG_FBNIC_LEDS) +=3D fbnic_led.o diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet= /meta/fbnic/fbnic.h index d0715695c43e..cf98beca53d3 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic.h @@ -97,6 +97,11 @@ struct fbnic_dev { =20 struct fbnic_fw_log fw_log; =20 + /* Used to synchronize updates to LED state and CSR */ + struct mutex led_mutex; + bool led_link_up; + struct fbnic_led_cdev leds[FBNIC_NUM_LEDS]; + /* MDIO bus for PHYs */ struct mii_bus *mdio_bus; =20 @@ -243,6 +248,14 @@ void fbnic_dbg_exit(void); =20 void fbnic_rpc_reset_valid_entries(struct fbnic_dev *fbd); =20 +#if IS_ENABLED(CONFIG_FBNIC_LEDS) +int fbnic_led_init(struct fbnic_dev *fbd); +void fbnic_led_exit(struct fbnic_dev *fbd); +#else +static inline int fbnic_led_init(struct fbnic_dev *fbd) { return 0; } +static inline void fbnic_led_exit(struct fbnic_dev *fbd) {} +#endif + int fbnic_mdiobus_create(struct fbnic_dev *fbd); =20 void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_versio= n); diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethe= rnet/meta/fbnic/fbnic_csr.h index 64b958df7774..6f4ae091652b 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h @@ -857,6 +857,21 @@ enum { #define FBNIC_SIG_PCS_INTR_LINK_DOWN CSR_BIT(1) #define FBNIC_SIG_PCS_INTR_LINK_UP CSR_BIT(0) #define FBNIC_SIG_PCS_INTR_MASK 0x11816 /* 0x46058 */ +#define FBNIC_SIG_LED 0x11820 /* 0x46080 */ +#define FBNIC_SIG_LED_OVERRIDE_EN CSR_GENMASK(2, 0) +#define FBNIC_SIG_LED_OVERRIDE_VAL CSR_GENMASK(6, 4) + +enum { + FBNIC_SIG_LED_OVERRIDE_ACTIVITY =3D 0x1, + FBNIC_SIG_LED_OVERRIDE_AMBER =3D 0x2, + FBNIC_SIG_LED_OVERRIDE_BLUE =3D 0x4, +}; + +#define FBNIC_SIG_LED_BLINK_RATE_MASK CSR_GENMASK(11, 8) +enum { + FBNIC_SIG_LED_BLINK_RATE_5HZ =3D 0xf, +}; + #define FBNIC_CSR_END_SIG 0x1184e /* CSR section delimiter */ =20 #define FBNIC_CSR_START_MAC_STAT 0x11a00 diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_devlink.c b/drivers/net/= ethernet/meta/fbnic/fbnic_devlink.c index 546e1c12d287..8aabec5143cd 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_devlink.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_devlink.c @@ -622,6 +622,8 @@ void fbnic_devlink_free(struct fbnic_dev *fbd) { struct devlink *devlink =3D priv_to_devlink(fbd); =20 + mutex_destroy(&fbd->led_mutex); + devlink_free(devlink); } =20 @@ -651,6 +653,8 @@ struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *p= dev) =20 fbd->mac_addr_boundary =3D FBNIC_RPC_TCAM_MACDA_DEFAULT_BOUNDARY; =20 + mutex_init(&fbd->led_mutex); + return fbd; } =20 diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/= ethernet/meta/fbnic/fbnic_ethtool.c index f14de2366854..3904081e24f9 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -2005,6 +2005,64 @@ fbnic_get_rmon_stats(struct net_device *netdev, *ranges =3D fbnic_rmon_ranges; } =20 +/** + * fbnic_set_phys_id - Used to strobe the MAC LEDs in a recognizable patte= rn + * @netdev: Interface/port to strobe the LEDs for + * @phys_id_state: State requested by the call + * + * This function can really be broken down into two parts. There are the + * ACTIVE/INACTIVE states which really are meant to be defining the start + * and stop of the LED strobing. There is also the ON/OFF states which are + * used to provide us with a way of telling us that we should be turning + * the LED on and/or off. + * + * We translate these calls and pass them off to the MAC layer. They will + * be used to initialize a strobe, then on and off will be used to cycle + * between the patterns, and finally we will restore the original LED stat= e. + * + * We will return 2 when we are requested to go active. This will tell the + * call that it will need to call back to turn on/off the LED twice every + * second. + * + * Return: blink in half second intervals on success, negative value on fa= ilure + */ +static int fbnic_set_phys_id(struct net_device *netdev, + enum ethtool_phys_id_state phys_id_state) +{ + struct fbnic_net *fbn =3D netdev_priv(netdev); + struct fbnic_dev *fbd =3D fbn->fbd; + const struct fbnic_mac *mac; + int cycle_interval =3D 0; + int state; + + mac =3D fbd->mac; + + if (!mac || !mac->set_led_state) + return -EOPNOTSUPP; + + switch (phys_id_state) { + case ETHTOOL_ID_ACTIVE: + state =3D FBNIC_LED_STROBE_INIT; + cycle_interval =3D 2; + break; + case ETHTOOL_ID_INACTIVE: + state =3D FBNIC_LED_RESTORE; + break; + case ETHTOOL_ID_ON: + state =3D FBNIC_LED_ON; + break; + case ETHTOOL_ID_OFF: + state =3D FBNIC_LED_OFF; + break; + default: + return -EINVAL; + } + + mac->set_led_state(fbd, state); + + return cycle_interval; +} + static void fbnic_get_link_ext_stats(struct net_device *netdev, struct ethtool_link_ext_stats *stats) { @@ -2062,6 +2120,7 @@ static const struct ethtool_ops fbnic_ethtool_ops =3D= { .get_eth_mac_stats =3D fbnic_get_eth_mac_stats, .get_eth_ctrl_stats =3D fbnic_get_eth_ctrl_stats, .get_rmon_stats =3D fbnic_get_rmon_stats, + .set_phys_id =3D fbnic_set_phys_id, }; =20 void fbnic_set_ethtool_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_led.c b/drivers/net/ethe= rnet/meta/fbnic/fbnic_led.c new file mode 100644 index 000000000000..44d0dc1be448 --- /dev/null +++ b/drivers/net/ethernet/meta/fbnic/fbnic_led.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) Meta Platforms, Inc. and affiliates. */ +#include +#include +#include + +#include "fbnic.h" +#include "fbnic_csr.h" +#include "fbnic_mac.h" +#include "fbnic_netdev.h" + +#define led_classdev_to_fbnic_led(cdev) \ + container_of(cdev, struct fbnic_led_cdev, led) + +static const char *fbnic_led_names[FBNIC_NUM_LEDS] =3D { + "activity", + "link-amber", + "link-blue" +}; + +static void fbnic_led_get_name(struct fbnic_dev *fbd, + int led_idx, char *name) +{ + snprintf(name, LED_MAX_NAME_SIZE, "%s-%s", + fbd->netdev->name, fbnic_led_names[led_idx]); +} + +static int fbnic_led_get_idx(struct fbnic_dev *fbd, + struct fbnic_led_cdev *ldev) +{ + return ldev - &fbd->leds[0]; +} + +static struct fbnic_dev *led_cdev_to_fbd(struct led_classdev *led_cdev) +{ + struct fbnic_led_cdev *ldev =3D led_classdev_to_fbnic_led(led_cdev); + + return ldev->fbd; +} + +static u32 fbnic_led_get_supported_modes(struct fbnic_dev *fbd, int led_id= x) +{ + u32 modes =3D 0; + + if (led_idx =3D=3D FBNIC_LED_ACTIVITY) { + modes =3D BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX); + + return modes; + } + + /* Set modes for link LEDs - note 40G not supported */ + modes =3D BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_LINK_25000) | + BIT(TRIGGER_NETDEV_LINK_50000) | + BIT(TRIGGER_NETDEV_LINK_100000); + + return modes; +} + +static int fbnic_led_hw_ctl_set(struct led_classdev *led_cdev, + unsigned long flags) +{ + struct fbnic_led_cdev *ldev =3D led_classdev_to_fbnic_led(led_cdev); + struct fbnic_dev *fbd =3D led_cdev_to_fbd(led_cdev); + int led_idx =3D fbnic_led_get_idx(fbd, ldev); + u32 supported_modes; + + supported_modes =3D fbnic_led_get_supported_modes(fbd, led_idx); + + if (flags & ~supported_modes) + return -EINVAL; + + /* Turn on activity LED only when both the TX and RX flags are set. */ + if (led_idx =3D=3D FBNIC_LED_ACTIVITY && (flags & supported_modes) && + flags !=3D supported_modes) { + dev_warn(fbd->dev, + "Invalid activity LED mode(s): 0x%lx\n", flags); + return -EINVAL; + } + + /* Preserve the configured modes for restoration after LED strobe */ + mutex_lock(&fbd->led_mutex); + ldev->enabled_modes =3D flags; + + if (ldev->strobe_mode) + dev_warn(fbd->dev, + "LED config takes effect after strobe completes.\n"); + + fbnic_led_update_csr(fbd); + mutex_unlock(&fbd->led_mutex); + + return 0; +} + +static int fbnic_led_hw_ctl_get(struct led_classdev *led_cdev, + unsigned long *flags) +{ + struct fbnic_led_cdev *ldev =3D led_classdev_to_fbnic_led(led_cdev); + struct fbnic_dev *fbd =3D led_cdev_to_fbd(led_cdev); + + mutex_lock(&fbd->led_mutex); + + *flags =3D ldev->enabled_modes; + + mutex_unlock(&fbd->led_mutex); + + return 0; +} + +static struct device *fbnic_led_hw_ctl_get_device(struct led_classdev *led= _cdev) +{ + struct fbnic_dev *fbd =3D led_cdev_to_fbd(led_cdev); + struct net_device *netdev =3D fbd->netdev; + + return &netdev->dev; +} + +static int fbnic_led_hw_ctl_is_supported(struct led_classdev *led_cdev, + unsigned long flags) +{ + struct fbnic_led_cdev *ldev =3D led_classdev_to_fbnic_led(led_cdev); + struct fbnic_dev *fbd =3D led_cdev_to_fbd(led_cdev); + int led_idx =3D fbnic_led_get_idx(fbd, ldev); + u32 modes; + + modes =3D fbnic_led_get_supported_modes(fbd, led_idx); + + if (led_idx =3D=3D FBNIC_LED_ACTIVITY && (flags & modes) && flags !=3D mo= des) + return -EOPNOTSUPP; + if (flags & ~modes) + return -EOPNOTSUPP; + + return 0; +} + +static int fbnic_led_brightness_set_blocking(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct fbnic_led_cdev *ldev =3D led_classdev_to_fbnic_led(led_cdev); + struct fbnic_dev *fbd =3D led_cdev_to_fbd(led_cdev); + int led_idx =3D fbnic_led_get_idx(fbd, ldev); + + mutex_lock(&fbd->led_mutex); + if (!brightness) { + fbd->leds[led_idx].enabled_modes =3D 0; + fbd->leds[led_idx].strobe_mode =3D 0; + } else { + u32 mode; + + switch (led_idx) { + case FBNIC_LED_ACTIVITY: + fbd->leds[led_idx].enabled_modes =3D + BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX); + break; + default: + mode =3D fbnic_led_get_link_speed_mode(fbd); + fbd->leds[led_idx].enabled_modes =3D mode; + break; + } + } + + fbnic_led_update_csr(fbd); + + mutex_unlock(&fbd->led_mutex); + + return 0; +} + +static int fbnic_led_setup(struct fbnic_dev *fbd, int led_idx) +{ + struct pci_dev *pdev =3D to_pci_dev(fbd->dev); + struct led_classdev *led_cdev; + + fbd->leds[led_idx].fbd =3D fbd; + led_cdev =3D &fbd->leds[led_idx].led; + led_cdev->name =3D fbd->leds[led_idx].name; + fbnic_led_get_name(fbd, led_idx, fbd->leds[led_idx].name); + led_cdev->max_brightness =3D 1; + led_cdev->hw_control_trigger =3D "netdev"; + led_cdev->flags |=3D LED_RETAIN_AT_SHUTDOWN; + led_cdev->hw_control_set =3D fbnic_led_hw_ctl_set; + led_cdev->hw_control_get =3D fbnic_led_hw_ctl_get; + led_cdev->hw_control_get_device =3D fbnic_led_hw_ctl_get_device; + led_cdev->hw_control_is_supported =3D fbnic_led_hw_ctl_is_supported; + led_cdev->brightness_set_blocking =3D fbnic_led_brightness_set_blocking; + + return led_classdev_register(&pdev->dev, led_cdev); +} + +/** + * fbnic_led_init - initialize the linux led interface for fbnic + * + * @fbd: FBNIC device structure + * + * Return: zero on success, negative value on failure + * + * This function creates three led devices for the fbnic device. One for t= he + * activity LED and two for the color LEDs. The successful initialization + * creates -activity, -link-amber and -link-blue + * under /sys/class/leds/ + */ +int fbnic_led_init(struct fbnic_dev *fbd) +{ + int i, ret; + + for (i =3D 0; i < FBNIC_NUM_LEDS; i++) { + ret =3D fbnic_led_setup(fbd, i); + + if (ret) + goto err_led_setup; + } + + return 0; + +err_led_setup: + while (i--) + led_classdev_unregister(&fbd->leds[i].led); + + return ret; +} + +void fbnic_led_exit(struct fbnic_dev *fbd) +{ + int i; + + for (i =3D 0; i < FBNIC_NUM_LEDS; i++) + led_classdev_unregister(&fbd->leds[i].led); +} diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c b/drivers/net/ethe= rnet/meta/fbnic/fbnic_mac.c index 53b7a938b4c2..c6b1130f9159 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c @@ -623,6 +623,53 @@ static bool fbnic_pmd_update_state(struct fbnic_dev *f= bd, bool signal_detect) return false; } =20 +u32 fbnic_get_link_speed(u8 link_speed) +{ + switch (link_speed) { + case FBNIC_FW_LINK_MODE_25CR: + return SPEED_25000; + case FBNIC_FW_LINK_MODE_50CR2: + case FBNIC_FW_LINK_MODE_50CR: + return SPEED_50000; + case FBNIC_FW_LINK_MODE_100CR2: + return SPEED_100000; + default: + return 0; + } +} + +static void fbnic_set_led_state(struct fbnic_dev *fbd, int state) +{ + mutex_lock(&fbd->led_mutex); + + /* alternating amber,blue IDs device every half second */ + switch (state) { + case FBNIC_LED_OFF: /* amber on, blue off */ + fbd->leds[FBNIC_LED_LINK_AMBER].strobe_mode =3D FBNIC_STROBE_ON; + fbd->leds[FBNIC_LED_LINK_BLUE].strobe_mode =3D FBNIC_STROBE_OFF; + break; + case FBNIC_LED_ON: /* amber off, blue on */ + fbd->leds[FBNIC_LED_LINK_AMBER].strobe_mode =3D FBNIC_STROBE_OFF; + fbd->leds[FBNIC_LED_LINK_BLUE].strobe_mode =3D FBNIC_STROBE_ON; + break; + case FBNIC_LED_RESTORE: + fbd->leds[FBNIC_LED_LINK_AMBER].strobe_mode =3D + FBNIC_STROBE_DISABLED; + fbd->leds[FBNIC_LED_LINK_BLUE].strobe_mode =3D + FBNIC_STROBE_DISABLED; + break; + case FBNIC_LED_STROBE_INIT: /* a no-op */ + /* Initialization is a no-op; LED toggling happens on ON/OFF */ + goto out_unlock; + default: + goto out_unlock; + } + + fbnic_led_update_csr(fbd); +out_unlock: + mutex_unlock(&fbd->led_mutex); +} + static bool fbnic_mac_get_link(struct fbnic_dev *fbd, u8 aui, u8 fec) { bool link; @@ -967,6 +1014,7 @@ static const struct fbnic_mac fbnic_mac_asic =3D { .link_down =3D fbnic_mac_link_down_asic, .link_up =3D fbnic_mac_link_up_asic, .get_sensor =3D fbnic_mac_get_sensor_asic, + .set_led_state =3D fbnic_set_led_state, }; =20 /** @@ -987,6 +1035,197 @@ int fbnic_mac_init(struct fbnic_dev *fbd) return 0; } =20 +/** + * __fbnic_led_get_link_speed_mode - Get link speed mode + * @curr_speed: ethtool speed + * + * Return: netdev trigger bit on success, 0 if link speed is not supported + * + * Convert ethtool speed to mode bit using parameter + */ +static u32 +__fbnic_led_get_link_speed_mode(u32 curr_speed) +{ + switch (curr_speed) { + case SPEED_25000: + return BIT(TRIGGER_NETDEV_LINK_25000); + case SPEED_50000: + return BIT(TRIGGER_NETDEV_LINK_50000); + case SPEED_100000: + return BIT(TRIGGER_NETDEV_LINK_100000); + default: + return 0; + } +} + +/** + * fbnic_led_get_link_speed_mode - Get link speed mode + * @fbd: FBNIC Device pointer + * + * Return: Link speed mode on success, 0 if link speed is not supported + * + * For the current link speed, this function returns trigger mode bit + */ +u32 fbnic_led_get_link_speed_mode(struct fbnic_dev *fbd) +{ + u32 curr_speed =3D fbnic_get_link_speed(fbd->fw_cap.link_speed); + + return __fbnic_led_get_link_speed_mode(curr_speed); +} + +/** + * fbnic_led_set_modes_ocp - Set LED state based on OCP link speed + * @fbd: FBNIC Device pointer + * + * Set LED state based on OCP link speed. This function sets up the + * LED state based on the current link speed while accounting for the + * OCP specs. Called from fbnic_led_link_up() on link state changes. + */ +void fbnic_led_set_modes_ocp(struct fbnic_dev *fbd) +{ + u32 speed_mode, curr_speed, max_speed; + + lockdep_assert_held(&fbd->led_mutex); + + /* Turn on the activity LED independent of the link speed */ + fbd->leds[FBNIC_LED_ACTIVITY].enabled_modes =3D BIT(TRIGGER_NETDEV_TX) | + BIT(TRIGGER_NETDEV_RX); + fbd->leds[FBNIC_LED_LINK_BLUE].enabled_modes =3D 0; + fbd->leds[FBNIC_LED_LINK_AMBER].enabled_modes =3D 0; + + curr_speed =3D fbnic_get_link_speed(fbd->fw_cap.link_speed); + if (!curr_speed) { + dev_warn(fbd->dev, + "Unsupported link speed detected.\n"); + goto bail; + } + + /* can't be zero */ + speed_mode =3D __fbnic_led_get_link_speed_mode(curr_speed); + + /* need max_speed for amber/blue leds values */ + max_speed =3D fbnic_get_link_speed(fbd->fw_cap.max_link_speed); + if (!max_speed) { + dev_warn(fbd->dev, + "Unsupported max link speed detected.\n"); + goto bail; + } + + /* Set the LED modes according to OCP specs */ + if (curr_speed < max_speed) + fbd->leds[FBNIC_LED_LINK_AMBER].enabled_modes =3D speed_mode; + else + fbd->leds[FBNIC_LED_LINK_BLUE].enabled_modes =3D speed_mode; + +bail: + /* sync csr with above changes */ + fbnic_led_update_csr(fbd); +} + +static u32 fbnic_led_get_current_mode(struct fbnic_dev *fbd) +{ + u32 modes =3D BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX); + + if (fbd->led_link_up) { + modes |=3D BIT(TRIGGER_NETDEV_LINK); + modes |=3D fbnic_led_get_link_speed_mode(fbd); + } + + return modes; +} + +/** + * fbnic_led_get_state - Get current LED state + * @fbd: FBNIC Device pointer + * @led_idx: LED index + * + * Get current LED state. This function returns the current LED state + * based on the currently configured enabled modes. If current configured + * modes are not set, it returns LED_OFF. + */ +static int fbnic_led_get_state(struct fbnic_dev *fbd, int led_idx) +{ + u8 strobe_mode =3D fbd->leds[led_idx].strobe_mode; + int led_state =3D LED_OFF; + u32 mask; + + if (strobe_mode =3D=3D FBNIC_STROBE_ON) + return LED_ON; + if (strobe_mode =3D=3D FBNIC_STROBE_OFF) + return LED_OFF; + + mask =3D fbnic_led_get_current_mode(fbd); + led_state =3D (mask & fbd->leds[led_idx].enabled_modes) ? + LED_ON : LED_OFF; + + return led_state; +} + +/** + * fbnic_led_update_csr - Update LED CSR + * @fbd: FBNIC Device pointer + * + * This function updates the LED CSR. This should be called every time + * the link speed changes, or when the enabled modes are changed via + * the linux LED API. + */ +void fbnic_led_update_csr(struct fbnic_dev *fbd) +{ + u32 led_csr =3D FBNIC_SIG_LED_ACTIVITY_OFF; + int led_state; + + lockdep_assert_held(&fbd->led_mutex); + + led_state =3D fbnic_led_get_state(fbd, FBNIC_LED_ACTIVITY); + if (led_state =3D=3D LED_ON) + led_csr =3D FBNIC_SIG_LED_ACTIVITY_DEFAULT; + + led_state =3D fbnic_led_get_state(fbd, FBNIC_LED_LINK_AMBER); + if (led_state =3D=3D LED_ON) + led_csr |=3D FBNIC_SIG_LED_AMBER_ON; + + led_state =3D fbnic_led_get_state(fbd, FBNIC_LED_LINK_BLUE); + if (led_state =3D=3D LED_ON) + led_csr |=3D FBNIC_SIG_LED_BLUE_ON; + + dev_dbg(fbd->dev, "writing led_csr %x\n", led_csr); + wr32(fbd, FBNIC_SIG_LED, led_csr); +} + +/** + * fbnic_led_link_up - Update LED state on link up + * @fbd: FBNIC Device pointer + * + * Called from phylink mac_link_up callback. Sets the internal link state + * and configures LED modes according to OCP specs based on current link s= peed. + */ +void fbnic_led_link_up(struct fbnic_dev *fbd) +{ + mutex_lock(&fbd->led_mutex); + + fbd->led_link_up =3D true; + fbnic_led_set_modes_ocp(fbd); + + mutex_unlock(&fbd->led_mutex); +} + +/** + * fbnic_led_link_down - Update LED state on link down + * @fbd: FBNIC Device pointer + * + * Called from phylink mac_link_down callback. Clears the internal link st= ate + * and updates the LED CSR to reflect link-down condition. + */ +void fbnic_led_link_down(struct fbnic_dev *fbd) +{ + mutex_lock(&fbd->led_mutex); + + fbd->led_link_up =3D false; + fbnic_led_update_csr(fbd); + + mutex_unlock(&fbd->led_mutex); +} + int fbnic_mac_ps_protect_to_config(struct fbnic_dev *fbd, u16 timeout_ms) { u16 old_timeout_ms =3D fbd->ps_timeout; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h b/drivers/net/ethe= rnet/meta/fbnic/fbnic_mac.h index 10f30e0e8f69..089afdde7b55 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h @@ -5,6 +5,8 @@ #define _FBNIC_MAC_H_ =20 #include +#include +#include =20 struct fbnic_dev; =20 @@ -33,6 +35,27 @@ struct fbnic_dev; FBNIC_MAC_RXB_PS_TO_MS(FIELD_MAX(FBNIC_RXB_PAUSE_STORM_THLD_TIME)) =20 #define FBNIC_MAX_JUMBO_FRAME_SIZE 9742 +#define FBNIC_NUM_LEDS 3 + +struct fbnic_led_cdev { + char name[LED_MAX_NAME_SIZE]; + struct led_classdev led; + struct fbnic_dev *fbd; + u32 enabled_modes; + u8 strobe_mode; +}; + +enum { + FBNIC_STROBE_DISABLED =3D 0, + FBNIC_STROBE_ON =3D 1, + FBNIC_STROBE_OFF =3D 2, +}; + +enum { + FBNIC_LED_ACTIVITY =3D 0, + FBNIC_LED_LINK_AMBER, + FBNIC_LED_LINK_BLUE, +}; =20 /* States loosely based on section 136.8.11.7.5 of IEEE 802.3-2022 Ethernet * Standard. These are needed to track the state of the PHY as it has a d= elay @@ -58,6 +81,13 @@ enum { FBNIC_LINK_EVENT_DOWN =3D 2, }; =20 +enum { + FBNIC_LED_STROBE_INIT, + FBNIC_LED_ON, + FBNIC_LED_OFF, + FBNIC_LED_RESTORE, +}; + /* Treat the FEC bits as a bitmask laid out as follows: * Bit 0: RS Enabled * Bit 1: BASER(Firecode) Enabled @@ -91,6 +121,29 @@ enum fbnic_sensor_id { FBNIC_SENSOR_VOLTAGE, /* Voltage in millivolts */ }; =20 +#define FBNIC_SIG_LED_ACTIVITY_DEFAULT \ + FIELD_PREP(FBNIC_SIG_LED_BLINK_RATE_MASK, \ + FBNIC_SIG_LED_BLINK_RATE_5HZ) +#define FBNIC_SIG_LED_ACTIVITY_ON \ + FIELD_PREP(FBNIC_SIG_LED_OVERRIDE_EN, \ + FBNIC_SIG_LED_OVERRIDE_ACTIVITY) +/* override_en=3D1 with override_val=3D0 forces the activity LED off + * while preserving the default blink rate setting + */ +#define FBNIC_SIG_LED_ACTIVITY_OFF \ + (FBNIC_SIG_LED_ACTIVITY_DEFAULT | \ + FBNIC_SIG_LED_ACTIVITY_ON) +#define FBNIC_SIG_LED_AMBER_ON \ + (FIELD_PREP(FBNIC_SIG_LED_OVERRIDE_EN, \ + FBNIC_SIG_LED_OVERRIDE_AMBER) | \ + FIELD_PREP(FBNIC_SIG_LED_OVERRIDE_VAL, \ + FBNIC_SIG_LED_OVERRIDE_AMBER)) +#define FBNIC_SIG_LED_BLUE_ON \ + (FIELD_PREP(FBNIC_SIG_LED_OVERRIDE_EN, \ + FBNIC_SIG_LED_OVERRIDE_BLUE) | \ + FIELD_PREP(FBNIC_SIG_LED_OVERRIDE_VAL, \ + FBNIC_SIG_LED_OVERRIDE_BLUE)) + /* This structure defines the interface hooks for the MAC. The MAC hooks * will be configured as a const struct provided with a set of function * pointers. @@ -112,6 +165,8 @@ enum fbnic_sensor_id { * Configure MAC for link down event * void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause); * Configure MAC for link up event; + * void (*set_led_state)(struct fbnic_dev *fbd, int state); + * Configure MAC for physical identification states * */ struct fbnic_mac { @@ -139,10 +194,17 @@ struct fbnic_mac { void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause); =20 int (*get_sensor)(struct fbnic_dev *fbd, int id, long *val); + void (*set_led_state)(struct fbnic_dev *fbd, int state); }; =20 int fbnic_mac_init(struct fbnic_dev *fbd); void fbnic_mac_get_fw_settings(struct fbnic_dev *fbd, u8 *aui, u8 *fec); +u32 fbnic_led_get_link_speed_mode(struct fbnic_dev *fbd); +u32 fbnic_get_link_speed(u8 link_speed); +void fbnic_led_set_modes_ocp(struct fbnic_dev *fbd); +void fbnic_led_update_csr(struct fbnic_dev *fbd); +void fbnic_led_link_up(struct fbnic_dev *fbd); +void fbnic_led_link_down(struct fbnic_dev *fbd); int fbnic_mac_ps_protect_to_config(struct fbnic_dev *fbd, u16 timeout); void fbnic_mac_ps_protect_handler(struct fbnic_dev *fbd); bool fbnic_mac_check_tx_pause(struct fbnic_dev *fbd); diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethe= rnet/meta/fbnic/fbnic_pci.c index 7e85b480203c..06a40081f603 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c @@ -368,9 +368,16 @@ static int fbnic_probe(struct pci_dev *pdev, const str= uct pci_device_id *ent) dev_err(&pdev->dev, "Netdev registration failed: %d\n", err); goto ifm_destroy_ptp; } + err =3D fbnic_led_init(fbd); + if (err) { + dev_err(&pdev->dev, "led init failed: %d\n", err); + goto led_init_fail; + } =20 return 0; =20 +led_init_fail: + fbnic_netdev_unregister(netdev); ifm_destroy_ptp: fbnic_ptp_destroy(fbd); ifm_free_netdev: @@ -408,6 +415,7 @@ static void fbnic_remove(struct pci_dev *pdev) if (!fbnic_init_failure(fbd)) { struct net_device *netdev =3D fbd->netdev; =20 + fbnic_led_exit(fbd); fbnic_netdev_unregister(netdev); cancel_delayed_work_sync(&fbd->service_task); fbnic_ptp_destroy(fbd); diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_phylink.c b/drivers/net/= ethernet/meta/fbnic/fbnic_phylink.c index 09c5225111be..86fccef901cc 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_phylink.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_phylink.c @@ -154,6 +154,7 @@ fbnic_phylink_mac_link_down(struct phylink_config *conf= ig, unsigned int mode, struct fbnic_dev *fbd =3D fbn->fbd; =20 fbd->mac->link_down(fbd); + fbnic_led_link_down(fbd); =20 fbn->link_down_events++; } @@ -172,6 +173,7 @@ fbnic_phylink_mac_link_up(struct phylink_config *config, fbnic_config_drop_mode(fbn, tx_pause); =20 fbd->mac->link_up(fbd, tx_pause, rx_pause); + fbnic_led_link_up(fbd); } =20 static const struct phylink_mac_ops fbnic_phylink_mac_ops =3D { --=20 2.43.0