From patchwork Wed Oct 25 08:25:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin 'ldir' Darbyshire-Bryant X-Patchwork-Id: 830136 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=lede-dev-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="bpIMduFH"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=darbyshire-bryant.me.uk header.i=@darbyshire-bryant.me.uk header.b="EO3jI64K"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yMNX84jxbz9sPk for ; Wed, 25 Oct 2017 19:26:32 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:Message-Id:Date:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=IKraBxcGxvb1jTHfu6OGhyIqhOPuHYDx8UmdXBkPItw=; b=bpIMduFHjzipdi 8Ksnbsmk//f5E3j4mNfEYPdpUGslAB6H8oTs7uX+hsaVjqFVZv4rpM7SPd0jJoZwt0irjUPqb3+4h 5G2U+xv9kOlfioHyz2Nov6VLR3ibI/3lwcway8SDCy5gjxwjqDgydOSHxiWodhKmjZkctZdZphT7T db7UAfOIyE9i7mL+FB2keReiSIJ83wzPbAPD1GA9QT8+T6qwBxzazxE8jMB65d9rmzCmKnKcprF3O G+/mR8/s850GXr6bYSLGAhNCujy5Ed74IlrhXHLPgI3am1sW5RNVjBstsYWK6DD9TMYpV8U3vtyIr yGS4PvNcwe42e1Dp38WQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e7H10-0004CG-Ui; Wed, 25 Oct 2017 08:26:18 +0000 Received: from mail-db5eur01on0082.outbound.protection.outlook.com ([104.47.2.82] helo=EUR01-DB5-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e7H0w-0004AP-GM for lede-dev@lists.infradead.org; Wed, 25 Oct 2017 08:26:17 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=darbyshire-bryant.me.uk; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=fbh2tWZqdP7CEz6AjhtvoeDU8zUk524d+0w8Hhv1PFE=; b=EO3jI64KFudBjCVL9XgnEOuAuhirTFw8Z55boOQ6L+KS3fkl5ljT7TeO/+uWfe7d/2nENpveI2ZSlPMbfwhgIt2eA1jhnIRuY8Imw4ckvhQcIZ0Wai+GpkRpjCjbKPi/j12RXSa+Li8dyfR2TVmimNaHylLp7ndUEfVXSiyKa1A= Received: from Animal.darbyshire-bryant.me.uk (2a02:c7f:1232:220::fb0e) by AM2PR07MB1027.eurprd07.prod.outlook.com (2a01:111:e400:8444::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.156.4; Wed, 25 Oct 2017 08:25:50 +0000 From: Kevin Darbyshire-Bryant To: lede-dev@lists.infradead.org Date: Wed, 25 Oct 2017 09:25:46 +0100 Message-Id: <1508919946-5416-1-git-send-email-ldir@darbyshire-bryant.me.uk> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 X-Originating-IP: [2a02:c7f:1232:220::fb0e] X-ClientProxiedBy: LO2P265CA0037.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:61::25) To AM2PR07MB1027.eurprd07.prod.outlook.com (2a01:111:e400:8444::24) X-MS-Office365-Filtering-Correlation-Id: 1d215e95-5ef2-4771-755a-08d51b820034 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(4534020)(4602075)(4603075)(4627075)(201702281549075)(2017052603238); SRVR:AM2PR07MB1027; X-Microsoft-Exchange-Diagnostics: 1; AM2PR07MB1027; 3:na1W3QD8QB4UWgYxWOy8OIsNNqbNvK/fvC9dY5bBKH7ZLJm49eMKH/OgZLdIYIG4JKnnJrBOVC1fXhJkvWnGHzpbsn12j33mjscud5xwaiMbRzYQRfErGbvqglri3jAG/WN9DIkj/MRKAofsZ6rAQprqFmFKbutyhUBMIuua7bi/ybBx9YIaniwEBj4Sm7GIxaixYa1yFTE97lOjxis0iOnjtu+54typT4tzL7a5vIZAguQQmQyAgURzgaG7Y1Lp; 25:DJAQlE32NtpK8+BJh5qo9Gi4pWUB4Zj5QaY1A9Eu+SlMxapJ+Lif+bNsbtViU3e8ufTEZAVe2JIp1AX3A+LFDWndtcpigQHD9Z+Qk/NIi22Qzci94sRuF2eU7G/Dt7zBZYr+0Osv1X27LPhHhEWq3NC1r/pdY27D65uw5eaNtqb0E0SvXtr947H3lHrSjjEkNAGIQUd8EmqKuvts/myW9SUK4s9EmAZdui5YuOk5ge0m0l1tOLvUp4ot6CAMsvKsmLw5ssD5Kc3PBHg1JTqzD7gRai1uetF50iiGriTekS7rm7CIaubXo1GZX5uGOdA27nB5XGNTqnswft/i0qJwg5j6fZ2wAyHYD4JZiZQMGrA=; 31:09ops2GaWUBpK5AEJxvzbvhZGPswNef9MlpOngHOhXW8u1fMbCVX8kROF248dCC7Km10tIKEYhHUVT7AQ+YUwApnKXM2bUX54EbsOuIC+ohsrjiyByOTcQ28VqkWf5a98e3X7mpRX7nqQ9zZZMM1KQOtkDW2EbWhiFMyRhDLEJ3EnNk0lYQ02SeLvqadYM89ge+u6t5MIMI6y4r+hqr88axiwMv22hXjgqipjaw9cJ0= X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM2PR07MB1027: X-Exchange-Antispam-Report-Test: UriScan:; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(3231020)(3002001)(93006095)(93001095)(100000703101)(100105400095)(10201501046)(6041248)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(20161123560025)(20161123562025)(2016111802025)(20161123558100)(6072148)(6043046)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:AM2PR07MB1027; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:AM2PR07MB1027; X-Microsoft-Exchange-Diagnostics: 1; AM2PR07MB1027; 4:1xrgRQxQ6LklDisxfmIdvlK3GDNyD5uffixBJ73fTprAkM00nNVPaXxlRmCnTvUgrGhr4JiXKMrs08ySgAbsC0aFYrIiGJNq+G5jVZf0vjqdcJ5OJgHvaM1CWnsIBA0OgG2ZDUS1i4I8II8NUmd0BJbrWQAeURaFifTPwYCqohwRkuuQHzPZXoTgNIFkmJaGfPrSk2TDuVFLTmfPvCfP+OmrLsczTTLoHV5rB9asa8HiisPoMTO58GpUvOlP9d/o X-Forefront-PRVS: 0471B73328 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(39830400002)(376002)(346002)(199003)(189002)(68736007)(6916009)(50986999)(105586002)(8676002)(6116002)(106356001)(97736004)(53936002)(107886003)(69596002)(50226002)(189998001)(5003940100001)(48376002)(4326008)(16586007)(7736002)(47776003)(305945005)(101416001)(8936002)(2906002)(316002)(575784001)(50466002)(53416004)(25786009)(478600001)(33646002)(36756003)(81156014)(81166006)(74482002)(5660300001)(6486002)(2351001)(6666003)(2361001)(42882006)(41533002); DIR:OUT; SFP:1101; SCL:1; SRVR:AM2PR07MB1027; H:Animal.darbyshire-bryant.me.uk; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: darbyshire-bryant.me.uk does not designate permitted sender hosts) Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=kevin@darbyshire-bryant.me.uk; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; AM2PR07MB1027; 23:gCle5ccxOdPomK0NP7cyw7KuQsrnBOJmGglxlRbb6?= lwoazUorrIdyjgvZ6B+qO+UbONK3Bs5IRocfnaiTZONyaAvHI/fMx7ddu6tXKvtlag78lCo93gnl2zce/4rjAogexaCWaT4Dpis2gPigxqqNca80YKCqCICwVPEAn44dlGzMR+72fctsRaYMRMlr4ME5JcxAXAdQZe8jI4JXQN98Ku6XaYWZMW6TTqbjcWU87wX7eVnyI7fP/veECYAgnzGRabve4ijwBSY/bjWvSSZpsSYkf5MrsceXlsJVoHrfAKLoHfhMOB5Sbo1fHWe4jK6RHdXfdaqDOLDyygu4X1eywWla/hd3osnYQkJUAzTraN/gVBeIBQWZlt73V61XhWYWUChzzo7RqnOD9037lwccU8WIib7LUbTPt3epg66OjEn5vpm8SqgvxSOv26C41G+9vdBlTauF6t9hZmeHZvxGs+yZr2r/oSdJwZUK6WPOGPaBlSjnXN/JYWns5uImcBfwSNFbT2QoQCGl+zBDSOXUuvBMtd2G9eJYIQFWkJZ7z8853l/IfVVXwPRbhLg4UUmsYHk59en85aRWVznuIYBk/OyFZs07TxR5UFLDwwJsQDCHCd5H3TNGoJr9gUQLV1zm7hAvOuqYRNwaHXD46/qdRlEZdPUOy+47lr/LDMnYWMMBISiuwj60S3spv5MlcUqfkNcspRxHaIF2ANcbetxGywYO7MM4URddct6brNPj3zMDQkuc1GA64ZPgGfR3FZa7cgFX6ljJXLVJ15k4vhMULnqYeQSvFvBVGUv+Dd8Gt0QRHSMcUNlhfX7zBbkpyQvW3UZxIyiDqvwSAUQPu/f1lPMVCs8d3k7hf6ovyGPaoLoFlBWCaRKgzInnPMeo7PoWjz1QK0gQvE09EW8Zc2Tc4MK4Hp0Vr/gn90aIhXhSvCG1aOK4ugadcNFTFEluQkZ9Dfb6KrPKU9Wjq5nZ5vD1qnzLbyenrc/mga1Dr6bp75yOOO3y31HvrmPkeOHIDKAIR/YfFmJ6Mw+7dED7g7ktH1UuNZ0x59iCsV0TneSAebokq87MhLHC0pT5ivJuAK+7od32p6vaBq+EVRPls8ONggojxGGVlL3NejylyEZasY= X-Microsoft-Exchange-Diagnostics: 1; AM2PR07MB1027; 6:P9AbqLYr/9NAw2RFukIdqpXlO7jX67dHRqkr3slTyOZHYsv7IV7hYimLlfdWwO1eXfyeqy1H+QiddfVzxQJ2RGn++pk3JHf2iWJZVOQ23XyNhHb2foA9m5WbWwoqGZ4bYMEAf0E1EvfDe73IWmuO1wexqHgt7T16aqyyQMLAJWWffUnxmIhxGYxvIz5mla7kXwN2eJWQ0PnDXB4Qc8ENIqt90AcZaRW/d8Z1nhowWl6hNjUASkcsmaGzMebIerkv/aFLNDs2eVXgPO2xVBia9D0qBEZTBSNdTXpocLUuWvUH9BMrkQV/cQ9tAJ8q48Gf7HKxOBYiGqCqC245UXtZWQ==; 5:7SSP3CTw8gB3u07m5yxJBxvtZLbMjjygVIjemASnhK18TAxAnD5B7c1hV1QDWMZZYvnGW+a5GnbmHJzU9n8MPIa6Zy4yl+8hQ/W66ctb6kzpNpN8LeOkQw7fCUYWOYopMXxdGNlo76h3QS+YFBSnAQ==; 24:aHFuRD1L+B4DEmwo4JhR09RhJqKsOKU25pTiOU2gJD8YBYx61HbcwCH9lpZAn4SNmsWI/n9srYkd5NeJO5mJot+IJ1/8Tvc0UsWe6ejIC/E=; 7:GazzNhL8jT2JVFR90PWNHDpr8SP1suWx0woCPlAmXn1fc42E754dUFrJW6Xw6zalJW1Rsw15e+MIQR7bndanL7Pov0cot9pdeSrU+CBIMCBj8VAXigL3CbYmP8Gh+HKKW4XIZwxvu0bX7//kmoqbA9hNmwubkmF8jhQGlwT6hZ/O/DzwsqYiY58K+wCIXr2HSoV1hJWTvDRkLHNbbZ2Nscg4HblPYmKcERiHWU/IsGY= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: darbyshire-bryant.me.uk X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Oct 2017 08:25:50.4992 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1d215e95-5ef2-4771-755a-08d51b820034 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 9151708b-c553-406f-8e56-694f435154a4 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM2PR07MB1027 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171025_012615_033873_20A7F15B X-CRM114-Status: GOOD ( 16.07 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [104.47.2.82 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H4 RBL: Very Good reputation (+4) [104.47.2.82 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Subject: [LEDE-DEV] [PATCH] generic: swconfig: add mode led attribute X-BeenThere: lede-dev@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Darbyshire-Bryant Sender: "Lede-dev" Errors-To: lede-dev-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add sysfs 'mode' attribute to swconfig controlled LEDs. swconfig 'link state' LEDs blink in the presence of port traffic. This behaviour becomes more obvious as switches start to support get_port_stats() e.g. commits 0369e358916ef092a1644334f5dd1412051b68a4, 3056d09b4046e0eb0f6de0f3f5432cd9fa86fc51, 4ddbc43cc15c2fa128a2f169964ef7eb508cf2c5, 4d8a66d9346373c2a7fcac5bdae3f662a9dbd9df. This blinking can be confusing/distracting if the switch has other LEDs used to indicate traffic. Provide a 'mode' sysfs attribute that controls the blink on traffic behaviour. mode - either "none" (LED is off) or a space separated list of one or more: link: LED's normal state reflects whether the link is up (has carrier) or not tx: LED blinks on transmitted data rx: LED blinks on receive data Note that 'link' considers any port speed mask that may be applicable. e.g. if an LED is configured to indicate 1Gbit link speed and mode is set to 'link rx tx' but the port is connected at 100Mbit then the LED will not light or blink. A mode of 'tx rx' will blink in the presence of traffic only if the port matches the rate (if configured) This maintains compatibility with existing behaviour. Attribute is 'link tx rx' by default for backwards compatible behaviour. Many thanks to Thibaut Varene for providing a more sensible led_event routine after I had mangled the original, and other coding style hints. Signed-off-by: Kevin Darbyshire-Bryant Acked-by: Thibaut VARENE --- .../generic/files/drivers/net/phy/swconfig_leds.c | 157 ++++++++++++++++++--- 1 file changed, 137 insertions(+), 20 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/swconfig_leds.c b/target/linux/generic/files/drivers/net/phy/swconfig_leds.c index 20b9a12..91824b7 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig_leds.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig_leds.c @@ -29,6 +29,15 @@ SWCONFIG_LED_PORT_SPEED_100 | \ SWCONFIG_LED_PORT_SPEED_1000) +#define SWCONFIG_LED_MODE_LINK 0x01 +#define SWCONFIG_LED_MODE_TX 0x02 +#define SWCONFIG_LED_MODE_RX 0x04 +#define SWCONFIG_LED_MODE_TXRX (SWCONFIG_LED_MODE_TX | \ + SWCONFIG_LED_MODE_RX) +#define SWCONFIG_LED_MODE_ALL (SWCONFIG_LED_MODE_LINK | \ + SWCONFIG_LED_MODE_TX | \ + SWCONFIG_LED_MODE_RX) + struct switch_led_trigger { struct led_trigger trig; struct switch_dev *swdev; @@ -36,7 +45,8 @@ struct switch_led_trigger { struct delayed_work sw_led_work; u32 port_mask; u32 port_link; - unsigned long long port_traffic[SWCONFIG_LED_NUM_PORTS]; + unsigned long long port_tx_traffic[SWCONFIG_LED_NUM_PORTS]; + unsigned long long port_rx_traffic[SWCONFIG_LED_NUM_PORTS]; u8 link_speed[SWCONFIG_LED_NUM_PORTS]; }; @@ -50,6 +60,7 @@ struct swconfig_trig_data { bool prev_link; unsigned long prev_traffic; enum led_brightness prev_brightness; + u8 mode; u8 speed_mask; }; @@ -113,18 +124,16 @@ swconfig_trig_port_mask_store(struct device *dev, struct device_attribute *attr, return ret; write_lock(&trig_data->lock); - changed = (trig_data->port_mask != port_mask); + trig_data->port_mask = port_mask; + write_unlock(&trig_data->lock); + if (changed) { - trig_data->port_mask = port_mask; if (port_mask == 0) swconfig_trig_set_brightness(trig_data, LED_OFF); - } - - write_unlock(&trig_data->lock); - if (changed) swconfig_trig_update_port_mask(led_cdev->trigger); + } return size; } @@ -135,11 +144,14 @@ swconfig_trig_port_mask_show(struct device *dev, struct device_attribute *attr, { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct swconfig_trig_data *trig_data = led_cdev->trigger_data; + u32 port_mask; read_lock(&trig_data->lock); - sprintf(buf, "%#x\n", trig_data->port_mask); + port_mask = trig_data->port_mask; read_unlock(&trig_data->lock); + sprintf(buf, "%#x\n", port_mask); + return strlen(buf) + 1; } @@ -153,11 +165,14 @@ static ssize_t swconfig_trig_speed_mask_show(struct device *dev, { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct swconfig_trig_data *trig_data = led_cdev->trigger_data; + u8 speed_mask; read_lock(&trig_data->lock); - sprintf(buf, "%#x\n", trig_data->speed_mask); + speed_mask = trig_data->speed_mask; read_unlock(&trig_data->lock); + sprintf(buf, "%#x\n", speed_mask); + return strlen(buf) + 1; } @@ -186,6 +201,79 @@ static ssize_t swconfig_trig_speed_mask_store(struct device *dev, static DEVICE_ATTR(speed_mask, 0644, swconfig_trig_speed_mask_show, swconfig_trig_speed_mask_store); +static ssize_t swconfig_trig_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct swconfig_trig_data *trig_data = led_cdev->trigger_data; + u8 mode; + + read_lock(&trig_data->lock); + mode = trig_data->mode; + read_unlock(&trig_data->lock); + + if (mode == 0) { + strcpy(buf, "none\n"); + } else { + if (mode & SWCONFIG_LED_MODE_LINK) + strcat(buf, "link "); + if (mode & SWCONFIG_LED_MODE_TX) + strcat(buf, "tx "); + if (mode & SWCONFIG_LED_MODE_RX) + strcat(buf, "rx "); + strcat(buf, "\n"); + } + + return strlen(buf)+1; +} + +static ssize_t swconfig_trig_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct swconfig_trig_data *trig_data = led_cdev->trigger_data; + char copybuf[128]; + int new_mode = -1; + char *p, *token; + + /* take a copy since we don't want to trash the inbound buffer when using strsep */ + strncpy(copybuf, buf, sizeof(copybuf)); + copybuf[sizeof(copybuf) - 1] = 0; + p = copybuf; + + while ((token = strsep(&p, " \t\n")) != NULL) { + if (!*token) + continue; + + if (new_mode < 0) + new_mode = 0; + + if (!strcmp(token, "none")) + new_mode = 0; + else if (!strcmp(token, "tx")) + new_mode |= SWCONFIG_LED_MODE_TX; + else if (!strcmp(token, "rx")) + new_mode |= SWCONFIG_LED_MODE_RX; + else if (!strcmp(token, "link")) + new_mode |= SWCONFIG_LED_MODE_LINK; + else + return -EINVAL; + } + + if (new_mode < 0) + return -EINVAL; + + write_lock(&trig_data->lock); + trig_data->mode = (u8)new_mode; + write_unlock(&trig_data->lock); + + return size; +} + +/* mode special file */ +static DEVICE_ATTR(mode, 0644, swconfig_trig_mode_show, + swconfig_trig_mode_store); + static void swconfig_trig_activate(struct led_classdev *led_cdev) { @@ -206,6 +294,7 @@ swconfig_trig_activate(struct led_classdev *led_cdev) trig_data->led_cdev = led_cdev; trig_data->swdev = sw_trig->swdev; trig_data->speed_mask = SWCONFIG_LED_PORT_SPEED_ALL; + trig_data->mode = SWCONFIG_LED_MODE_ALL; led_cdev->trigger_data = trig_data; err = device_create_file(led_cdev->dev, &dev_attr_port_mask); @@ -216,8 +305,15 @@ swconfig_trig_activate(struct led_classdev *led_cdev) if (err) goto err_dev_free; + err = device_create_file(led_cdev->dev, &dev_attr_mode); + if (err) + goto err_mode_free; + return; +err_mode_free: + device_remove_file(led_cdev->dev, &dev_attr_speed_mask); + err_dev_free: device_remove_file(led_cdev->dev, &dev_attr_port_mask); @@ -237,10 +333,17 @@ swconfig_trig_deactivate(struct led_classdev *led_cdev) if (trig_data) { device_remove_file(led_cdev->dev, &dev_attr_port_mask); device_remove_file(led_cdev->dev, &dev_attr_speed_mask); + device_remove_file(led_cdev->dev, &dev_attr_mode); kfree(trig_data); } } +/* + * link off -> led off (can't be any other reason to turn it on) + * link on: + * mode link: led on by default only if speed matches, else off + * mode txrx: blink only if speed matches, else off + */ static void swconfig_trig_led_event(struct switch_led_trigger *sw_trig, struct led_classdev *led_cdev) @@ -248,7 +351,8 @@ swconfig_trig_led_event(struct switch_led_trigger *sw_trig, struct swconfig_trig_data *trig_data; u32 port_mask; bool link; - u8 speed_mask; + u8 speed_mask, mode; + enum led_brightness led_base, led_blink; trig_data = led_cdev->trigger_data; if (!trig_data) @@ -257,35 +361,48 @@ swconfig_trig_led_event(struct switch_led_trigger *sw_trig, read_lock(&trig_data->lock); port_mask = trig_data->port_mask; speed_mask = trig_data->speed_mask; + mode = trig_data->mode; read_unlock(&trig_data->lock); link = !!(sw_trig->port_link & port_mask); if (!link) { - if (link != trig_data->prev_link) - swconfig_trig_set_brightness(trig_data, LED_OFF); - } else { + if (trig_data->prev_brightness != LED_OFF) + swconfig_trig_set_brightness(trig_data, LED_OFF); /* and stop */ + } + else { unsigned long traffic; int speedok; /* link speed flag */ int i; + led_base = LED_FULL; + led_blink = LED_OFF; traffic = 0; speedok = 0; for (i = 0; i < SWCONFIG_LED_NUM_PORTS; i++) { - if (port_mask & (1 << i)) + if (port_mask & (1 << i)) { if (sw_trig->link_speed[i] & speed_mask) { - traffic += sw_trig->port_traffic[i]; + traffic += ((mode & SWCONFIG_LED_MODE_TX) ? + sw_trig->port_tx_traffic[i] : 0) + + ((mode & SWCONFIG_LED_MODE_RX) ? + sw_trig->port_rx_traffic[i] : 0); speedok = 1; } + } } if (speedok) { /* At least one port speed matches speed_mask */ - if (trig_data->prev_brightness != LED_FULL) + if (!(mode & SWCONFIG_LED_MODE_LINK)) { + led_base = LED_OFF; + led_blink = LED_FULL; + } + + if (trig_data->prev_brightness != led_base) swconfig_trig_set_brightness(trig_data, - LED_FULL); + led_base); else if (traffic != trig_data->prev_traffic) swconfig_trig_set_brightness(trig_data, - LED_OFF); + led_blink); } else if (trig_data->prev_brightness != LED_OFF) swconfig_trig_set_brightness(trig_data, LED_OFF); @@ -371,8 +488,8 @@ swconfig_led_work_func(struct work_struct *work) memset(&port_stats, '\0', sizeof(port_stats)); swdev->ops->get_port_stats(swdev, i, &port_stats); - sw_trig->port_traffic[i] = port_stats.tx_bytes + - port_stats.rx_bytes; + sw_trig->port_tx_traffic[i] = port_stats.tx_bytes; + sw_trig->port_rx_traffic[i] = port_stats.rx_bytes; } }