From patchwork Mon Oct 21 21:01:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwan R Timmer X-Patchwork-Id: 1180881 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="MD0O/1tF"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46xpzX6DCTz9sP4 for ; Tue, 22 Oct 2019 08:04:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730339AbfJUVEN (ORCPT ); Mon, 21 Oct 2019 17:04:13 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:37263 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730273AbfJUVEN (ORCPT ); Mon, 21 Oct 2019 17:04:13 -0400 Received: by mail-wr1-f68.google.com with SMTP id e11so6833256wrv.4 for ; Mon, 21 Oct 2019 14:04:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SJv1PDeyKQxzosO6KQSoZipAwqZnnSGMrGr+gZL05jo=; b=MD0O/1tFwl9gbCSw7ePGVr5jKyn5EQUhXBSfHuFskA8lP0LugmHf5zTsW2UbnMtzrf nKXWK94J/eVAvmDRqhX2/YClDP/EwybhemMNpSuloYZILrxvu8sm2k1/2Huj9zfclNne jFUCE/fGhn9slc6fZpca+uajgiS+HZAl34YgPFP3oVfbsjk+HoI0GWQwzgrpOPttDB5H jZE9V5y3xWsafPerloNSzs/Ve1y0+V3D6M2y6jtY/Z5IDEAI9cV5DEH+ElOhPcuKqda9 zYVgnguA1RZB9PYNSUM5PvUajYLtCVuwUWC+D13fVRgdONdipCAfM0yG6gFgy6lLWvks CxJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SJv1PDeyKQxzosO6KQSoZipAwqZnnSGMrGr+gZL05jo=; b=btEmCBBeSeWebCHhgd7FjGdqTWdMgvR9qUhzLSQCojL7oEIOlACdexnPLIMWVvPvWY OvdPJ8rrV1PkXUjN2lbA+PmJi9JiSVHiv5vngvl/sUR5McJvKJjs0BeZ2Y/HL3EgbETQ mWQzhXVZ4WyQqDopxsRD6jROyCWRKnIjdOvuzov0/TCzUDlnz4IIJkReY0cd0SE2DhaD sb9b53jIrgdba8zkHUV5SdHJ9l825Wi9PvozoQJhGxhbQ9yg6V13FGeNn+ZMN8/FQBEx MmW/quZ1XUy7r4AJQItvb+rTXsJCE2yFOiKGf/qqVCR+gSvb9HtUEZ4kaAU0Dh0x8jSw 6Naw== X-Gm-Message-State: APjAAAU5SWKdcZMDKWQ4DRICnvLXWcFU77ugab0/Oq1ql/6CzIeIKkJ+ 1I7EHulneK5Oqu/8ri19Ghd+2US+eTXTHg== X-Google-Smtp-Source: APXvYqw8U8nD33hMnO1B3qVy8ga3winJeoIeXIirWe6bNMcSnZp5T9GSL3E7Bk9LOkzXw2TKY3gY0w== X-Received: by 2002:a5d:4aca:: with SMTP id y10mr209471wrs.292.1571691850681; Mon, 21 Oct 2019 14:04:10 -0700 (PDT) Received: from i5wan.lan (214-247-144-85.ftth.glasoperator.nl. [85.144.247.214]) by smtp.gmail.com with ESMTPSA id g5sm14309949wmg.12.2019.10.21.14.04.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Oct 2019 14:04:10 -0700 (PDT) From: Iwan R Timmer To: netdev@vger.kernel.org Cc: andrew@lunn.ch, vivien.didelot@gmail.com, f.fainelli@gmail.com, davem@davemloft.net, Iwan R Timmer Subject: [PATCH net-next v2 1/2] net: dsa: mv88e6xxx: Split monitor port configuration Date: Mon, 21 Oct 2019 23:01:42 +0200 Message-Id: <20191021210143.119426-2-irtimmer@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191021210143.119426-1-irtimmer@gmail.com> References: <20191021210143.119426-1-irtimmer@gmail.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Separate the configuration of the egress and ingress monitor port. This allows the port mirror functionality to do ingress and egress port mirroring to separate ports. Signed-off-by: Iwan R Timmer --- drivers/net/dsa/mv88e6xxx/chip.c | 9 ++++++++- drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- drivers/net/dsa/mv88e6xxx/global1.c | 23 +++++++++++------------ drivers/net/dsa/mv88e6xxx/global1.h | 6 ++++-- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6787d560e9e3..e9735346838d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2378,7 +2378,14 @@ static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port) if (chip->info->ops->set_egress_port) { err = chip->info->ops->set_egress_port(chip, - upstream_port); + true, + upstream_port); + if (err) + return err; + + err = chip->info->ops->set_egress_port(chip, + false, + upstream_port); if (err) return err; } diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index e9b1a1ac9a8e..42ce3109ebc9 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -464,7 +464,8 @@ struct mv88e6xxx_ops { int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port, uint64_t *data); int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port); - int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port); + int (*set_egress_port)(struct mv88e6xxx_chip *chip, bool ingress, + int port); #define MV88E6XXX_CASCADE_PORT_NONE 0xe #define MV88E6XXX_CASCADE_PORT_MULTIPLE 0xf diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 25ec4c0ac589..35b9610cbe73 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -263,7 +263,8 @@ int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip) /* Offset 0x1a: Monitor Control */ /* Offset 0x1a: Monitor & MGMT Control on some devices */ -int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) +int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, bool ingress, + int port) { u16 reg; int err; @@ -272,11 +273,12 @@ int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) if (err) return err; - reg &= ~(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK | - MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); + reg &= ~(ingress ? MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK : + MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); - reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK) | - port << __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); + reg |= port << (ingress ? + __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK) : + __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK)); return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg); } @@ -310,17 +312,14 @@ static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip, return mv88e6xxx_g1_write(chip, MV88E6390_G1_MONITOR_MGMT_CTL, reg); } -int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) +int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, bool ingress, + int port) { u16 ptr; int err; - ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST; - err = mv88e6390_g1_monitor_write(chip, ptr, port); - if (err) - return err; - - ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST; + ptr = ingress ? MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST : + MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST; err = mv88e6390_g1_monitor_write(chip, ptr, port); if (err) return err; diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index 0870fcc8bfc8..ef7e13f71927 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -287,8 +287,10 @@ int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip); int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip); void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val); int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip); -int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port); -int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port); +int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, bool ingress, + int port); +int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, bool ingress, + int port); int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); From patchwork Mon Oct 21 21:01:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iwan R Timmer X-Patchwork-Id: 1180882 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="HydMKHLm"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46xpzY4Xs4z9sP3 for ; Tue, 22 Oct 2019 08:04:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387406AbfJUVEP (ORCPT ); Mon, 21 Oct 2019 17:04:15 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:38721 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728943AbfJUVEP (ORCPT ); Mon, 21 Oct 2019 17:04:15 -0400 Received: by mail-wr1-f67.google.com with SMTP id v9so4288529wrq.5 for ; Mon, 21 Oct 2019 14:04:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hBEv6QYPF0Jw/Q+VKatlmEgADK+n5RKsMHBvpwrZDdE=; b=HydMKHLmsweHpm+KHAhWFvDGIBeFGiHjVr3pXVl0c/PIYKlc9Ljoltj4OlVt7kH5JF LQ8pfUQ665VMMUpl3sBRRjtqwZ6p/lQ9QZ1ChXkUiYkI3sYRZoDgAeLJ/mjfEVpyKD6O 4icXsAEqWzdQ27AvzQwpc6PO65Qiz1wRHYbFl5rmD0UWv+LpZznTGNZmb5YY9pvn2sPw XWrzTdGgTC2NEhFD9qIZwALTraU62odh1kqOwqyojl6jI6MKVvezWX1rIfmji6liF+Kq S9yX4ERvZrYyRokE8S2og6cymsJZFXlyoz7/LNTYbBh6nYQ+tcNT60dg99Pkia767Mqv OHyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hBEv6QYPF0Jw/Q+VKatlmEgADK+n5RKsMHBvpwrZDdE=; b=QRTp7EfcLdpm3KZKnwufB4JY/yAG4Qz1JOmKvnZe9upW1dROlVb5kAY4EOU/BFTY8j bSwqBlYfyfEWO9f/SZglwZwD/ZzUH/ByWJAFWBzYMRAiWFtUu1JT8P4z6sDbdMfQKLjQ GrfVBCKr8/W220HcW+aAE7rofe3lkmgAGyPOfTDfsynMy6T2YTL2xviUMCL7JQ/OCAem 9Di6bT5S5bpuItJNxFXmSbZKOvoWWTzSVpjKao0Y/ZFDMDGhm2wCK7HpklEHy23DzzOO WLgWmFlMz7ztXuiGUi54OFo2Wer39VnlD5yRD0zwSemFys0P36+qBRRQRj9UfHKwacWg FYlw== X-Gm-Message-State: APjAAAVX1lv5xzJjRbox4wlrY1xiMgdUdqa3MJ8jcHJxQio/LHwnmJko 2BC70stW/WRRW0cHzJvCKz9zQEl5frFD6Q== X-Google-Smtp-Source: APXvYqzRvSrYG5+T1eGF/7QzHlK0aR6XJvNjZi/GcsOK4C32G+T9MPf67ui3I7kMYk3/7oGG3EXoEA== X-Received: by 2002:adf:ebcb:: with SMTP id v11mr218317wrn.24.1571691851409; Mon, 21 Oct 2019 14:04:11 -0700 (PDT) Received: from i5wan.lan (214-247-144-85.ftth.glasoperator.nl. [85.144.247.214]) by smtp.gmail.com with ESMTPSA id g5sm14309949wmg.12.2019.10.21.14.04.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Oct 2019 14:04:10 -0700 (PDT) From: Iwan R Timmer To: netdev@vger.kernel.org Cc: andrew@lunn.ch, vivien.didelot@gmail.com, f.fainelli@gmail.com, davem@davemloft.net, Iwan R Timmer Subject: [PATCH net-next v2 2/2] net: dsa: mv88e6xxx: Add support for port mirroring Date: Mon, 21 Oct 2019 23:01:43 +0200 Message-Id: <20191021210143.119426-3-irtimmer@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191021210143.119426-1-irtimmer@gmail.com> References: <20191021210143.119426-1-irtimmer@gmail.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add support for configuring port mirroring through the cls_matchall classifier. We do a full ingress and/or egress capture towards a capture port. It allows setting a different capture port for ingress and egress traffic. It keeps track of the mirrored ports and the destination ports to prevent changes to the capture port while other ports are being mirrored. Signed-off-by: Iwan R Timmer --- drivers/net/dsa/mv88e6xxx/chip.c | 70 +++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/chip.h | 6 +++ drivers/net/dsa/mv88e6xxx/global1.c | 11 ++++- drivers/net/dsa/mv88e6xxx/port.c | 29 ++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 2 + 5 files changed, 117 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index e9735346838d..14e71bc98513 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4921,6 +4921,74 @@ static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port, return err; } +static int mv88e6xxx_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) +{ + struct mv88e6xxx_chip *chip = ds->priv; + bool other_mirrors = false; + int i; + int err; + + if (!chip->info->ops->set_egress_port) + return -EOPNOTSUPP; + + mutex_lock(&chip->reg_lock); + if ((ingress ? chip->ingress_dest_port : chip->egress_dest_port) != + mirror->to_local_port) { + for (i = 0; i < mv88e6xxx_num_ports(chip); i++) + other_mirrors |= ingress ? + chip->ports[i].mirror_ingress : + chip->ports[i].mirror_egress; + + /* Can't change egress port when other mirror is active */ + if (other_mirrors) { + err = -EBUSY; + goto out; + } + + err = chip->info->ops->set_egress_port(chip, + ingress, + mirror->to_local_port); + if (err) + goto out; + } + + err = mv88e6xxx_port_set_mirror(chip, port, ingress, true); +out: + mutex_unlock(&chip->reg_lock); + + return err; +} + +static void mv88e6xxx_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) +{ + struct mv88e6xxx_chip *chip = ds->priv; + bool other_mirrors = false; + int i; + + mutex_lock(&chip->reg_lock); + if (mv88e6xxx_port_set_mirror(chip, port, mirror->ingress, false)) + dev_err(ds->dev, "p%d: failed to disable mirroring\n", port); + + for (i = 0; i < mv88e6xxx_num_ports(chip); i++) + other_mirrors |= mirror->ingress ? + chip->ports[i].mirror_ingress : + chip->ports[i].mirror_egress; + + /* Reset egress port when no other mirror is active */ + if (!other_mirrors) { + if (chip->info->ops->set_egress_port(chip, + mirror->ingress, + dsa_upstream_port(ds, + port))); + dev_err(ds->dev, "failed to set egress port\n"); + } + + mutex_unlock(&chip->reg_lock); +} + static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, bool unicast, bool multicast) { @@ -4975,6 +5043,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .port_mdb_prepare = mv88e6xxx_port_mdb_prepare, .port_mdb_add = mv88e6xxx_port_mdb_add, .port_mdb_del = mv88e6xxx_port_mdb_del, + .port_mirror_add = mv88e6xxx_port_mirror_add, + .port_mirror_del = mv88e6xxx_port_mirror_del, .crosschip_bridge_join = mv88e6xxx_crosschip_bridge_join, .crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave, .port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 42ce3109ebc9..e33a1426dac3 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -228,6 +228,8 @@ struct mv88e6xxx_port { u64 vtu_miss_violation; u8 cmode; unsigned int serdes_irq; + bool mirror_ingress; + bool mirror_egress; }; struct mv88e6xxx_chip { @@ -310,6 +312,10 @@ struct mv88e6xxx_chip { u16 evcap_config; u16 enable_count; + /* Current ingress and egress monitor ports */ + int egress_dest_port; + int ingress_dest_port; + /* Per-port timestamping resources. */ struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS]; diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 35b9610cbe73..ecef80d9d88f 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -280,7 +280,16 @@ int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port, __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK) : __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK)); - return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg); + err = mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg); + if (err) + return err; + + if (ingress) + chip->ingress_dest_port = port; + else + chip->egress_dest_port = port; + + return 0; } /* Older generations also call this the ARP destination. It has been diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 15ef81654b67..3e7aae56f27a 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -1181,6 +1181,35 @@ int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg); } +int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port, + bool ingress, bool mirror) +{ + u16 reg; + u16 bit; + int err; + + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®); + if (err) + return err; + + bit = ingress ? MV88E6XXX_PORT_CTL2_INGRESS_MONITOR : + MV88E6XXX_PORT_CTL2_EGRESS_MONITOR; + reg &= ~bit; + + if (mirror) + reg |= bit; + + err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg); + if (!err) { + if (ingress) + chip->ports[port].mirror_ingress = mirror; + else + chip->ports[port].mirror_egress = mirror; + } + + return err; +} + int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, u16 mode) { diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 03a480cd71b9..e9d7b66fd49e 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -368,6 +368,8 @@ int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int upstream_port); +int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port, + bool ingress, bool mirror); int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port); int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port);