* Re: [PATCH net-next v2 2/3] net: dsa: mv88e6xxx: add support for bridge flags
From: Florian Fainelli @ 2019-02-19 23:53 UTC (permalink / raw)
To: Russell King - ARM Linux admin, Vivien Didelot
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, netdev
In-Reply-To: <20190219233408.th2wukhmtxdmeivj@shell.armlinux.org.uk>
On 2/19/19 3:34 PM, Russell King - ARM Linux admin wrote:
> On Tue, Feb 19, 2019 at 05:00:59PM +0000, Russell King - ARM Linux admin wrote:
>> I've just changed my last patch to set these modes from
>> dsa_port_bridge_join() and dsa_port_bridge_leave(), and while testing,
>> I notice this on the ZII rev B board:
>>
>> At boot (without anything connected to any of the switch ports):
>>
>> br0: port 1(lan0) entered blocking state
>> br0: port 1(lan0) entered disabled state
>> device lan0 entered promiscuous mode
>> device eth1 entered promiscuous mode
>> br0: port 2(lan1) entered blocking state
>> br0: port 2(lan1) entered disabled state
>> device lan1 entered promiscuous mode
>> ...
>>
>> I then removed lan0 from the bridge:
>>
>> device lan0 left promiscuous mode
>> br0: port 1(lan0) entered disabled state
>>
>> and then added it back:
>>
>> br0: port 1(lan0) entered blocking state
>> br0: port 1(lan0) entered disabled state
>> device lan0 entered promiscuous mode
>>
>> Now, you'd expect lan0 and lan1 to be configured the same at this
>> point, and the same as it was before lan0 was removed from the bridge?
>> lan0 is port 0, lan1 is port 1 on this switch - and the register debug
>> says:
>>
>> GLOBAL GLOBAL2 SERDES 0 1 2 3 4 5 6
>> 0: c800 0 1140 500f 500f 500f 500f 500f 4e07 4d04
>> ...
>> 4: 40a8 258 1e0 43c 43d 43d 7c 430 53f 373f
>>
>> Note that port 0 is in disabled state, but port 1 and 2 are in
>> blocking state... but wait, the kernel printed a message saying it was
>> in disabled state!
>>
>> If I do the same for lan1, port 1 above changed from 0x43d to 0x433 as
>> expected, and then returns to 0x43c.
>>
>> It looks like DSA isn't always in sync with bridge as per port state.
>
> Okay, the problem is what we do when we up the port.
>
> When the port is added to the bridge device, and it's down, the bridge
> code sets the STP state to "disabled".
>
> Then when we up the interface, dsa_slave_open() calls dsa_port_enable(),
> which then decides to change the STP state on its own without reference
> to the state assigned by net/bridge:
>
> int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
> {
> u8 stp_state = dp->bridge_dev ? BR_STATE_BLOCKING : BR_STATE_FORWARDING;
> ...
> dsa_port_set_state_now(dp, stp_state);
> ...
> }
>
> I can understand setting the state to BR_STATE_FORWARDING for
> stand-alone ports, but why for bridged ports when the bridge code has
> already taken care of configuring the STP state of the port?
There was no reason for doing that in commit
b73adef67765b72f2a0d01ef15aff9d784dc85da ("net: dsa: integrate with
SWITCHDEV for HW bridging") other than copying what rocker had done
(which served as model back then), and which got changed the next day in
rocker with: e47172ab7e4176883077b454286bbd5b87b5f488 ("rocker: put port
in FORWADING state after leaving bridge")
Good catch!
--
Florian
^ permalink raw reply
* [PATCH v2 net-next 0/4] net: dsa: microchip: add MIB counters support
From: Tristram.Ha @ 2019-02-19 23:56 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
From: Tristram Ha <Tristram.Ha@microchip.com>
This series of patches is to modify the KSZ9477 DSA driver to read MIB
counters periodically to avoid overflow.
The MIB counters should be read only when there is link. Otherwise it is
a waste of time as hardware never increases the counters.
Functions are added to check the port link status so that MIB counters
read call is used efficiently.
v2
- Create macro similar to readx_poll_timeout to use with switch
- Create ksz_port_cleanup function so that variables like on_ports and
live_ports can be updated inside it.
v1
- Use readx_poll_timeout
- Do not clear MIB counters when port is enabled
- Do not advertise 1000 half-duplex mode when port is enabled
- Do not use freeze function as MIB counters may miss counts
Tristram Ha (4):
net: dsa: microchip: prepare PHY for proper advertisement
net: dsa: microchip: add MIB counter reading support
net: dsa: microchip: get port link status
net: dsa: microchip: remove unnecessary include headers
drivers/net/dsa/microchip/ksz9477.c | 137 +++++++++++++++++----------
drivers/net/dsa/microchip/ksz_common.c | 163 ++++++++++++++++++++++++++++++++-
drivers/net/dsa/microchip/ksz_common.h | 27 +++++-
drivers/net/dsa/microchip/ksz_priv.h | 14 +--
4 files changed, 284 insertions(+), 57 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v2 net-next 2/4] net: dsa: microchip: add MIB counter reading support
From: Tristram.Ha @ 2019-02-19 23:57 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550620623-13036-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Add background MIB counter reading support.
Port MIB counters should only be read when there is link. Otherwise it is
a waste of time as hardware never increases those counters. There are
exceptions as some switches keep track of dropped counts no matter waht.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
---
drivers/net/dsa/microchip/ksz9477.c | 118 ++++++++++++++++++++------------
drivers/net/dsa/microchip/ksz_common.c | 121 +++++++++++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz_common.h | 24 ++++++-
drivers/net/dsa/microchip/ksz_priv.h | 9 ++-
4 files changed, 224 insertions(+), 48 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 4573b6e..e2d74c7 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -18,8 +18,8 @@
#include <net/switchdev.h>
#include "ksz_priv.h"
-#include "ksz_common.h"
#include "ksz9477_reg.h"
+#include "ksz_common.h"
static const struct {
int index;
@@ -259,6 +259,71 @@ static int ksz9477_reset_switch(struct ksz_device *dev)
return 0;
}
+static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
+ u64 *cnt)
+{
+ struct ksz_port *p = &dev->ports[port];
+ u32 data;
+ int ret;
+
+ /* retain the flush/freeze bit */
+ data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
+ data |= MIB_COUNTER_READ;
+ data |= (addr << MIB_COUNTER_INDEX_S);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
+
+ ret = ksz_pread_poll_timeout(ksz_pread32, dev, port,
+ REG_PORT_MIB_CTRL_STAT__4, data,
+ !(data & MIB_COUNTER_READ), 10, 1000);
+
+ /* failed to read MIB. get out of loop */
+ if (ret < 0) {
+ dev_dbg(dev->dev, "Failed to get MIB\n");
+ return;
+ }
+
+ /* count resets upon read */
+ ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
+ *cnt += data;
+}
+
+static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+ u64 *dropped, u64 *cnt)
+{
+ addr = ksz9477_mib_names[addr].index;
+ ksz9477_r_mib_cnt(dev, port, addr, cnt);
+}
+
+static void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
+{
+ u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
+ struct ksz_port *p = &dev->ports[port];
+
+ /* enable/disable the port for flush/freeze function */
+ mutex_lock(&p->mib.cnt_mutex);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val);
+
+ /* used by MIB counter reading code to know freeze is enabled */
+ p->freeze = freeze;
+ mutex_unlock(&p->mib.cnt_mutex);
+}
+
+static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
+{
+ struct ksz_port_mib *mib = &dev->ports[port].mib;
+
+ /* flush all enabled port MIB counters */
+ mutex_lock(&mib->cnt_mutex);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
+ MIB_COUNTER_FLUSH_FREEZE);
+ ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
+ ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
+ mutex_unlock(&mib->cnt_mutex);
+
+ mib->cnt_ptr = 0;
+ memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
+}
+
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
int port)
{
@@ -342,47 +407,6 @@ static void ksz9477_get_strings(struct dsa_switch *ds, int port,
}
}
-static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
- uint64_t *buf)
-{
- struct ksz_device *dev = ds->priv;
- int i;
- u32 data;
- int timeout;
-
- mutex_lock(&dev->stats_mutex);
-
- for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
- data = MIB_COUNTER_READ;
- data |= ((ksz9477_mib_names[i].index & 0xFF) <<
- MIB_COUNTER_INDEX_S);
- ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
-
- timeout = 1000;
- do {
- ksz_pread32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
- &data);
- usleep_range(1, 10);
- if (!(data & MIB_COUNTER_READ))
- break;
- } while (timeout-- > 0);
-
- /* failed to read MIB. get out of loop */
- if (!timeout) {
- dev_dbg(dev->dev, "Failed to get MIB\n");
- break;
- }
-
- /* count resets upon read */
- ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
-
- dev->mib_value[i] += (uint64_t)data;
- buf[i] = dev->mib_value[i];
- }
-
- mutex_unlock(&dev->stats_mutex);
-}
-
static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
u8 member)
{
@@ -1151,9 +1175,14 @@ static int ksz9477_setup(struct dsa_switch *ds)
/* queue based egress rate limit */
ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true);
+ /* enable global MIB counter freeze function */
+ ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true);
+
/* start switch */
ksz_cfg(dev, REG_SW_OPERATION, SW_START, true);
+ ksz_init_mib_timer(dev);
+
return 0;
}
@@ -1287,6 +1316,7 @@ static int ksz9477_switch_init(struct ksz_device *dev)
if (!dev->ports)
return -ENOMEM;
for (i = 0; i < dev->mib_port_cnt; i++) {
+ mutex_init(&dev->ports[i].mib.cnt_mutex);
dev->ports[i].mib.counters =
devm_kzalloc(dev->dev,
sizeof(u64) *
@@ -1311,6 +1341,10 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
.phy_setup = ksz9477_phy_setup,
.port_setup = ksz9477_port_setup,
+ .r_mib_cnt = ksz9477_r_mib_cnt,
+ .r_mib_pkt = ksz9477_r_mib_pkt,
+ .freeze_mib = ksz9477_freeze_mib,
+ .port_init_cnt = ksz9477_port_init_cnt,
.shutdown = ksz9477_reset_switch,
.detect = ksz9477_switch_detect,
.init = ksz9477_switch_init,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 6f72842..9270570 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -40,6 +40,101 @@ void ksz_update_port_member(struct ksz_device *dev, int port)
}
EXPORT_SYMBOL_GPL(ksz_update_port_member);
+static void port_r_cnt(struct ksz_device *dev, int port)
+{
+ struct ksz_port_mib *mib = &dev->ports[port].mib;
+ u64 *dropped;
+
+ /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
+ while (mib->cnt_ptr < dev->reg_mib_cnt) {
+ dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
+ &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+
+ /* last one in storage */
+ dropped = &mib->counters[dev->mib_cnt];
+
+ /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
+ while (mib->cnt_ptr < dev->mib_cnt) {
+ dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
+ dropped, &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+ mib->cnt_ptr = 0;
+}
+
+static void ksz_mib_read_work(struct work_struct *work)
+{
+ struct ksz_device *dev = container_of(work, struct ksz_device,
+ mib_read);
+ struct ksz_port_mib *mib;
+ struct ksz_port *p;
+ int i;
+
+ for (i = 0; i < dev->mib_port_cnt; i++) {
+ p = &dev->ports[i];
+
+ /* Only read MIB counters when the port is told to do. */
+ if (!p->read)
+ continue;
+ mib = &p->mib;
+ mutex_lock(&mib->cnt_mutex);
+ port_r_cnt(dev, i);
+ mutex_unlock(&mib->cnt_mutex);
+ }
+}
+
+static void mib_monitor(struct timer_list *t)
+{
+ struct ksz_device *dev = from_timer(dev, t, mib_read_timer);
+ const struct dsa_port *dp;
+ struct net_device *netdev;
+ struct ksz_port_mib *mib;
+ struct ksz_port *p;
+ int i;
+
+ mod_timer(&dev->mib_read_timer, jiffies + dev->mib_read_interval);
+
+ /* Check which port needs to read MIB counters. */
+ for (i = 0; i < dev->mib_port_cnt; i++) {
+ p = &dev->ports[i];
+ if (!p->on)
+ continue;
+ dp = dsa_to_port(dev->ds, i);
+ netdev = dp->slave;
+
+ mib = &p->mib;
+ mutex_lock(&mib->cnt_mutex);
+
+ /* Read only dropped counters when link is not up. */
+ if (netdev && netdev->phydev && !netdev->phydev->link)
+ mib->cnt_ptr = dev->reg_mib_cnt;
+ mutex_unlock(&mib->cnt_mutex);
+ p->read = true;
+ }
+ schedule_work(&dev->mib_read);
+}
+
+void ksz_init_mib_timer(struct ksz_device *dev)
+{
+ int i;
+
+ /* Read MIB counters every 30 seconds to avoid overflow. */
+ dev->mib_read_interval = msecs_to_jiffies(30000);
+
+ INIT_WORK(&dev->mib_read, ksz_mib_read_work);
+ timer_setup(&dev->mib_read_timer, mib_monitor, 0);
+
+ for (i = 0; i < dev->mib_port_cnt; i++)
+ dev->dev_ops->port_init_cnt(dev, i);
+
+ /* Start the timer 2 seconds later. */
+ dev->mib_read_timer.expires = jiffies + msecs_to_jiffies(2000);
+ add_timer(&dev->mib_read_timer);
+}
+EXPORT_SYMBOL_GPL(ksz_init_mib_timer);
+
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
{
struct ksz_device *dev = ds->priv;
@@ -72,6 +167,26 @@ int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
}
EXPORT_SYMBOL_GPL(ksz_sset_count);
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf)
+{
+ const struct dsa_port *dp = dsa_to_port(ds, port);
+ struct ksz_device *dev = ds->priv;
+ struct net_device *netdev;
+ struct ksz_port_mib *mib;
+
+ mib = &dev->ports[port].mib;
+ mutex_lock(&mib->cnt_mutex);
+
+ /* Only read dropped counters if no link. */
+ netdev = dp->slave;
+ if (netdev && netdev->phydev && !netdev->phydev->link)
+ mib->cnt_ptr = dev->reg_mib_cnt;
+ port_r_cnt(dev, port);
+ memcpy(buf, mib->counters, dev->mib_cnt * sizeof(u64));
+ mutex_unlock(&mib->cnt_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats);
+
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *br)
{
@@ -339,6 +454,12 @@ int ksz_switch_register(struct ksz_device *dev,
void ksz_switch_remove(struct ksz_device *dev)
{
+ /* timer started */
+ if (dev->mib_read_timer.expires) {
+ del_timer_sync(&dev->mib_read_timer);
+ flush_work(&dev->mib_read);
+ }
+
dev->dev_ops->exit(dev);
dsa_unregister_switch(dev->ds);
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 2dd832d..0b0ed3d 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -1,19 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0
* Microchip switch driver common header
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
void ksz_update_port_member(struct ksz_device *dev, int port);
+void ksz_init_mib_timer(struct ksz_device *dev);
/* Common DSA access functions */
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *br);
void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
@@ -211,4 +213,24 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
ksz_write8(dev, addr, data);
}
+/* Modify from readx_poll_timeout in iopoll.h. */
+#define ksz_pread_poll_timeout(op, dev, p, addr, val, cond, sleep_us, \
+ timeout_us) \
+({ \
+ ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
+ might_sleep_if(sleep_us); \
+ for (;;) { \
+ op(dev, p, addr, &(val)); \
+ if (cond) \
+ break; \
+ if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
+ op(dev, p, addr, &(val)); \
+ break; \
+ } \
+ if (sleep_us) \
+ usleep_range((sleep_us >> 2) + 1, sleep_us); \
+ } \
+ (cond) ? 0 : -ETIMEDOUT; \
+})
+
#endif
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 0fdc58b..1d2d98f 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -14,8 +14,6 @@
#include <linux/etherdevice.h>
#include <net/dsa.h>
-#include "ksz9477_reg.h"
-
struct ksz_io_ops;
struct vlan_table {
@@ -23,6 +21,7 @@ struct vlan_table {
};
struct ksz_port_mib {
+ struct mutex cnt_mutex; /* structure access */
u8 cnt_ptr;
u64 *counters;
};
@@ -38,7 +37,8 @@ struct ksz_port {
u32 fiber:1; /* port is fiber */
u32 sgmii:1; /* port is SGMII */
u32 force:1;
- u32 link_just_down:1; /* link just goes down */
+ u32 read:1; /* read MIB counters in background */
+ u32 freeze:1; /* MIB counter freeze is enabled */
struct ksz_port_mib mib;
};
@@ -79,8 +79,6 @@ struct ksz_device {
struct vlan_table *vlan_cache;
- u64 mib_value[TOTAL_SWITCH_COUNTER_NUM];
-
u8 *txbuf;
struct ksz_port *ports;
@@ -153,6 +151,7 @@ struct ksz_dev_ops {
u64 *cnt);
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt);
+ void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
void (*port_init_cnt)(struct ksz_device *dev, int port);
int (*shutdown)(struct ksz_device *dev);
int (*detect)(struct ksz_device *dev);
--
1.9.1
^ permalink raw reply related
* [PATCH v2 net-next 3/4] net: dsa: microchip: get port link status
From: Tristram.Ha @ 2019-02-19 23:57 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550620623-13036-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Get port link status to know whether to read MIB counters when the link
is going down. Add port_cleanup function to read MIB counters the last
time as after the port is disabled the PHY is also powered down.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
---
drivers/net/dsa/microchip/ksz9477.c | 2 ++
drivers/net/dsa/microchip/ksz_common.c | 39 ++++++++++++++++++++++++++++++++--
drivers/net/dsa/microchip/ksz_common.h | 3 +++
drivers/net/dsa/microchip/ksz_priv.h | 1 +
4 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index e2d74c7..6ad28e2 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1191,6 +1191,7 @@ static int ksz9477_setup(struct dsa_switch *ds)
.setup = ksz9477_setup,
.phy_read = ksz9477_phy_read16,
.phy_write = ksz9477_phy_write16,
+ .adjust_link = ksz_adjust_link,
.port_enable = ksz_enable_port,
.port_disable = ksz_disable_port,
.get_strings = ksz9477_get_strings,
@@ -1340,6 +1341,7 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
.cfg_port_member = ksz9477_cfg_port_member,
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
.phy_setup = ksz9477_phy_setup,
+ .port_cleanup = ksz_port_cleanup,
.port_setup = ksz9477_port_setup,
.r_mib_cnt = ksz9477_r_mib_cnt,
.r_mib_pkt = ksz9477_r_mib_pkt,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 9270570..c4bb67f 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -20,6 +20,22 @@
#include "ksz_priv.h"
+void ksz_port_cleanup(struct ksz_device *dev, int port)
+{
+ /* Read all MIB counters when the link is going down. */
+ if (dev->live_ports & (1 << port)) {
+ struct ksz_port *p = &dev->ports[port];
+
+ p->read = true;
+ schedule_work(&dev->mib_read);
+ }
+
+ /* Common code for port cleanup. */
+ dev->on_ports &= ~(1 << port);
+ dev->live_ports &= ~(1 << port);
+}
+EXPORT_SYMBOL_GPL(ksz_port_cleanup);
+
void ksz_update_port_member(struct ksz_device *dev, int port)
{
struct ksz_port *p;
@@ -156,6 +172,26 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
}
EXPORT_SYMBOL_GPL(ksz_phy_write16);
+void ksz_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev)
+{
+ struct ksz_device *dev = ds->priv;
+ struct ksz_port *p = &dev->ports[port];
+
+ if (!phydev->link) {
+ /* Read all MIB counters when the link is going down. */
+ if (dev->live_ports & (1 << port)) {
+ p->read = true;
+ schedule_work(&dev->mib_read);
+ }
+ dev->live_ports &= ~(1 << port);
+ } else {
+ /* Remember which port is connected and active. */
+ dev->live_ports |= (1 << port) & dev->on_ports;
+ }
+}
+EXPORT_SYMBOL_GPL(ksz_adjust_link);
+
int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
{
struct ksz_device *dev = ds->priv;
@@ -367,8 +403,7 @@ void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
{
struct ksz_device *dev = ds->priv;
- dev->on_ports &= ~(1 << port);
- dev->live_ports &= ~(1 << port);
+ dev->dev_ops->port_cleanup(dev, port);
/* port_stp_state_set() will be called after to disable the port so
* there is no need to do anything.
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 0b0ed3d..ebe6f8e 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -7,6 +7,7 @@
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
+void ksz_port_cleanup(struct ksz_device *dev, int port);
void ksz_update_port_member(struct ksz_device *dev, int port);
void ksz_init_mib_timer(struct ksz_device *dev);
@@ -14,6 +15,8 @@
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
+void ksz_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev);
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 1d2d98f..a1d84c1 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -137,6 +137,7 @@ struct ksz_dev_ops {
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
void (*phy_setup)(struct ksz_device *dev, int port,
struct phy_device *phy);
+ void (*port_cleanup)(struct ksz_device *dev, int port);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
--
1.9.1
^ permalink raw reply related
* [PATCH v2 net-next 4/4] net: dsa: microchip: remove unnecessary include headers
From: Tristram.Ha @ 2019-02-19 23:57 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550620623-13036-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Remove unnecessary header include.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/microchip/ksz9477.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 6ad28e2..a9465c1 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -5,14 +5,10 @@
* Copyright (C) 2017-2019 Microchip Technology Inc.
*/
-#include <linux/delay.h>
-#include <linux/export.h>
-#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_data/microchip-ksz.h>
#include <linux/phy.h>
-#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <net/dsa.h>
#include <net/switchdev.h>
--
1.9.1
^ permalink raw reply related
* [PATCH v2 net-next 1/4] net: dsa: microchip: prepare PHY for proper advertisement
From: Tristram.Ha @ 2019-02-19 23:57 UTC (permalink / raw)
To: Sergio Paracuellos, Andrew Lunn, Florian Fainelli, Pavel Machek
Cc: Tristram Ha, UNGLinuxDriver, netdev
In-Reply-To: <1550620623-13036-1-git-send-email-Tristram.Ha@microchip.com>
From: Tristram Ha <Tristram.Ha@microchip.com>
Prepare PHY for proper advertisement as sometimes the PHY in the switch
has its own problems even though it may share the PHY id from regular PHY
but the fixes in the PHY driver do not apply.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
---
drivers/net/dsa/microchip/ksz9477.c | 13 ++++++++++++-
drivers/net/dsa/microchip/ksz_common.c | 3 ++-
drivers/net/dsa/microchip/ksz_priv.h | 4 +++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 674d77e..4573b6e 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -2,7 +2,7 @@
/*
* Microchip KSZ9477 switch driver main logic
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#include <linux/delay.h>
@@ -966,6 +966,16 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
PORT_MIRROR_SNIFFER, false);
}
+static void ksz9477_phy_setup(struct ksz_device *dev, int port,
+ struct phy_device *phy)
+{
+ if (port < dev->phy_port_cnt) {
+ /* The MAC actually cannot run in 1000 half-duplex mode. */
+ phy_remove_link_mode(phy,
+ ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+ }
+}
+
static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
u8 data8;
@@ -1299,6 +1309,7 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
.get_port_addr = ksz9477_get_port_addr,
.cfg_port_member = ksz9477_cfg_port_member,
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
+ .phy_setup = ksz9477_phy_setup,
.port_setup = ksz9477_port_setup,
.shutdown = ksz9477_reset_switch,
.detect = ksz9477_switch_detect,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 8a5111f..6f72842 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2,7 +2,7 @@
/*
* Microchip switch driver main logic
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#include <linux/delay.h>
@@ -238,6 +238,7 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
/* setup slave port */
dev->dev_ops->port_setup(dev, port, false);
+ dev->dev_ops->phy_setup(dev, port, phy);
/* port_stp_state_set() will be called after to enable the port so
* there is no need to do anything.
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 60b4901..0fdc58b 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -2,7 +2,7 @@
*
* Microchip KSZ series switch common definitions
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2019 Microchip Technology Inc.
*/
#ifndef __KSZ_PRIV_H
@@ -137,6 +137,8 @@ struct ksz_dev_ops {
u32 (*get_port_addr)(int port, int offset);
void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
+ void (*phy_setup)(struct ksz_device *dev, int port,
+ struct phy_device *phy);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
--
1.9.1
^ permalink raw reply related
* Re: [PATCH iproute2] bridge: make mcast_flood description consistent
From: Russell King - ARM Linux admin @ 2019-02-20 0:05 UTC (permalink / raw)
To: Vivien Didelot; +Cc: netdev, stephen
In-Reply-To: <20190219234738.17009-1-vivien.didelot@gmail.com>
On Tue, Feb 19, 2019 at 06:47:38PM -0500, Vivien Didelot wrote:
> This patch simply changes the description of the mcast_flood flag
> with "flood" instead of "be flooded with" to avoid confusion, and be
> consistent with the description of the flooding flag, which "Controls
> whether a given port will *flood* unicast traffic for which there is
> no FDB entry."
Hi Vivien,
I'm not sure if it's in the current iproute2, but there is a
discrepency between the arguments for 'bridge' stated in the man page
and the description thereof:
bridge link set dev DEV [ cost COST ] [ priority PRIO ] [ state STATE
...
} ] [ learning_sync { on | off } ] [ flood { on | off } ] [
^^^^^^^^^^^^^^^^^^
vs
flooding on or flooding off
Controls whether a given port will flood unicast traffic for
which there is no FDB entry. By default this flag is on.
vs the command actually accepting "flood" not "flooding". I spotted
that in iproute2-4.20.0. I haven't had a chance to generate a patch
that yet and work out how to submit it, but thanks for leading the
way!
>
> Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
> ---
> man/man8/bridge.8 | 2 +-
> man/man8/ip-link.8.in | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
> index 72210f62..03b33d34 100644
> --- a/man/man8/bridge.8
> +++ b/man/man8/bridge.8
> @@ -361,7 +361,7 @@ switch.
>
> .TP
> .BR "mcast_flood on " or " mcast_flood off "
> -Controls whether a given port will be flooded with multicast traffic for which there is no MDB entry. By default this flag is on.
> +Controls whether a given port will flood multicast traffic for which there is no MDB entry. By default this flag is on.
>
> .TP
> .BR "neigh_suppress on " or " neigh_suppress off "
> diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
> index 5132f514..cef489a4 100644
> --- a/man/man8/ip-link.8.in
> +++ b/man/man8/ip-link.8.in
> @@ -2155,7 +2155,7 @@ queries.
> option above.
>
> .BR mcast_flood " { " on " | " off " }"
> -- controls whether a given port will be flooded with multicast traffic for which there is no MDB entry.
> +- controls whether a given port will flood multicast traffic for which there is no MDB entry.
>
> .BI group_fwd_mask " MASK "
> - set the group forward mask. This is the bitmask that is applied to decide whether to forward incoming frames destined to link-local addresses, ie addresses of the form 01:80:C2:00:00:0X (defaults to 0, ie the bridge does not forward any link-local frames coming on this port).
> --
> 2.20.1
>
>
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
^ permalink raw reply
* Re: [PATCH net-next v2 2/3] net: dsa: mv88e6xxx: add support for bridge flags
From: Russell King - ARM Linux admin @ 2019-02-20 0:07 UTC (permalink / raw)
To: Florian Fainelli
Cc: Vivien Didelot, Andrew Lunn, Heiner Kallweit, David S. Miller,
netdev
In-Reply-To: <bbea158f-c541-4a64-958f-c86eeedcbfcb@gmail.com>
On Tue, Feb 19, 2019 at 03:53:50PM -0800, Florian Fainelli wrote:
> On 2/19/19 3:34 PM, Russell King - ARM Linux admin wrote:
> > On Tue, Feb 19, 2019 at 05:00:59PM +0000, Russell King - ARM Linux admin wrote:
> >> I've just changed my last patch to set these modes from
> >> dsa_port_bridge_join() and dsa_port_bridge_leave(), and while testing,
> >> I notice this on the ZII rev B board:
> >>
> >> At boot (without anything connected to any of the switch ports):
> >>
> >> br0: port 1(lan0) entered blocking state
> >> br0: port 1(lan0) entered disabled state
> >> device lan0 entered promiscuous mode
> >> device eth1 entered promiscuous mode
> >> br0: port 2(lan1) entered blocking state
> >> br0: port 2(lan1) entered disabled state
> >> device lan1 entered promiscuous mode
> >> ...
> >>
> >> I then removed lan0 from the bridge:
> >>
> >> device lan0 left promiscuous mode
> >> br0: port 1(lan0) entered disabled state
> >>
> >> and then added it back:
> >>
> >> br0: port 1(lan0) entered blocking state
> >> br0: port 1(lan0) entered disabled state
> >> device lan0 entered promiscuous mode
> >>
> >> Now, you'd expect lan0 and lan1 to be configured the same at this
> >> point, and the same as it was before lan0 was removed from the bridge?
> >> lan0 is port 0, lan1 is port 1 on this switch - and the register debug
> >> says:
> >>
> >> GLOBAL GLOBAL2 SERDES 0 1 2 3 4 5 6
> >> 0: c800 0 1140 500f 500f 500f 500f 500f 4e07 4d04
> >> ...
> >> 4: 40a8 258 1e0 43c 43d 43d 7c 430 53f 373f
> >>
> >> Note that port 0 is in disabled state, but port 1 and 2 are in
> >> blocking state... but wait, the kernel printed a message saying it was
> >> in disabled state!
> >>
> >> If I do the same for lan1, port 1 above changed from 0x43d to 0x433 as
> >> expected, and then returns to 0x43c.
> >>
> >> It looks like DSA isn't always in sync with bridge as per port state.
> >
> > Okay, the problem is what we do when we up the port.
> >
> > When the port is added to the bridge device, and it's down, the bridge
> > code sets the STP state to "disabled".
> >
> > Then when we up the interface, dsa_slave_open() calls dsa_port_enable(),
> > which then decides to change the STP state on its own without reference
> > to the state assigned by net/bridge:
> >
> > int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
> > {
> > u8 stp_state = dp->bridge_dev ? BR_STATE_BLOCKING : BR_STATE_FORWARDING;
> > ...
> > dsa_port_set_state_now(dp, stp_state);
> > ...
> > }
> >
> > I can understand setting the state to BR_STATE_FORWARDING for
> > stand-alone ports, but why for bridged ports when the bridge code has
> > already taken care of configuring the STP state of the port?
>
> There was no reason for doing that in commit
> b73adef67765b72f2a0d01ef15aff9d784dc85da ("net: dsa: integrate with
> SWITCHDEV for HW bridging") other than copying what rocker had done
> (which served as model back then), and which got changed the next day in
> rocker with: e47172ab7e4176883077b454286bbd5b87b5f488 ("rocker: put port
> in FORWADING state after leaving bridge")
>
> Good catch!
As mentioned on IRC, I'll send a patch for this tomorrow for the net
tree once I've untangled it from the floods work.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
^ permalink raw reply
* Re: [GIT] Networking
From: pr-tracker-bot @ 2019-02-20 0:30 UTC (permalink / raw)
To: David Miller; +Cc: torvalds, akpm, netdev, linux-kernel
In-Reply-To: <20190219.143326.1810127131443236789.davem@davemloft.net>
The pull request you sent on Tue, 19 Feb 2019 14:33:26 -0800 (PST):
> git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git refs/heads/master
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/40e196a906d969fd10d885c692d2674b3d657006
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker
^ permalink raw reply
* linux-next: manual merge of the net-next tree with the bpf tree
From: Stephen Rothwell @ 2019-02-20 0:37 UTC (permalink / raw)
To: David Miller, Networking, Daniel Borkmann, Alexei Starovoitov
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
Stanislav Fomichev
[-- Attachment #1: Type: text/plain, Size: 8862 bytes --]
Hi all,
Today's linux-next merge of the net-next tree got a conflict in:
tools/testing/selftests/bpf/test_progs.c
between commit:
f6be4d16039b ("selftests/bpf: make sure signal interrupts BPF_PROG_TEST_RUN")
from the bpf tree and commits:
bf0f0fd93945 ("selftests/bpf: add simple BPF_PROG_TEST_RUN examples for flow dissector")
ab963beb9f5d ("selftests/bpf: add bpf_spin_lock C test")
ba72a7b4badb ("selftests/bpf: test for BPF_F_LOCK")
from the net-next tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc tools/testing/selftests/bpf/test_progs.c
index 7842e3749b19,c52bd90fbb34..000000000000
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@@ -10,8 -10,8 +10,9 @@@
#include <string.h>
#include <assert.h>
#include <stdlib.h>
+ #include <stdarg.h>
#include <time.h>
+#include <signal.h>
#include <linux/types.h>
typedef __u16 __sum16;
@@@ -28,9 -28,8 +29,9 @@@
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/types.h>
+#include <sys/time.h>
#include <fcntl.h>
-
+ #include <pthread.h>
#include <linux/bpf.h>
#include <linux/err.h>
#include <bpf/bpf.h>
@@@ -1914,47 -1925,189 +1927,230 @@@ out
bpf_object__close(obj);
}
+static void sigalrm_handler(int s) {}
+static struct sigaction sigalrm_action = {
+ .sa_handler = sigalrm_handler,
+};
+
+static void test_signal_pending(void)
+{
+ struct bpf_insn prog[4096];
+ struct itimerval timeo = {
+ .it_value.tv_usec = 100000, /* 100ms */
+ };
+ __u32 duration, retval;
+ int prog_fd;
+ int err;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(prog); i++)
+ prog[i] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0);
+ prog[ARRAY_SIZE(prog) - 1] = BPF_EXIT_INSN();
+
+ prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER,
+ prog, ARRAY_SIZE(prog),
+ "GPL", 0, NULL, 0);
+ CHECK(prog_fd < 0, "test-run", "errno %d\n", errno);
+
+ err = sigaction(SIGALRM, &sigalrm_action, NULL);
+ CHECK(err, "test-run-signal-sigaction", "errno %d\n", errno);
+
+ err = setitimer(ITIMER_REAL, &timeo, NULL);
+ CHECK(err, "test-run-signal-timer", "errno %d\n", errno);
+
+ err = bpf_prog_test_run(prog_fd, 0xffffffff, &pkt_v4, sizeof(pkt_v4),
+ NULL, NULL, &retval, &duration);
+ CHECK(err != -1 || errno != EINTR || duration > 1000000000,
+ "test-run-signal-run",
+ "err %d errno %d retval %d\n",
+ err, errno, retval);
+
+ signal(SIGALRM, SIG_DFL);
+}
+
+ #define CHECK_FLOW_KEYS(desc, got, expected) \
+ CHECK(memcmp(&got, &expected, sizeof(got)) != 0, \
+ desc, \
+ "nhoff=%u/%u " \
+ "thoff=%u/%u " \
+ "addr_proto=0x%x/0x%x " \
+ "is_frag=%u/%u " \
+ "is_first_frag=%u/%u " \
+ "is_encap=%u/%u " \
+ "n_proto=0x%x/0x%x " \
+ "sport=%u/%u " \
+ "dport=%u/%u\n", \
+ got.nhoff, expected.nhoff, \
+ got.thoff, expected.thoff, \
+ got.addr_proto, expected.addr_proto, \
+ got.is_frag, expected.is_frag, \
+ got.is_first_frag, expected.is_first_frag, \
+ got.is_encap, expected.is_encap, \
+ got.n_proto, expected.n_proto, \
+ got.sport, expected.sport, \
+ got.dport, expected.dport)
+
+ static struct bpf_flow_keys pkt_v4_flow_keys = {
+ .nhoff = 0,
+ .thoff = sizeof(struct iphdr),
+ .addr_proto = ETH_P_IP,
+ .ip_proto = IPPROTO_TCP,
+ .n_proto = bpf_htons(ETH_P_IP),
+ };
+
+ static struct bpf_flow_keys pkt_v6_flow_keys = {
+ .nhoff = 0,
+ .thoff = sizeof(struct ipv6hdr),
+ .addr_proto = ETH_P_IPV6,
+ .ip_proto = IPPROTO_TCP,
+ .n_proto = bpf_htons(ETH_P_IPV6),
+ };
+
+ static void test_flow_dissector(void)
+ {
+ struct bpf_flow_keys flow_keys;
+ struct bpf_object *obj;
+ __u32 duration, retval;
+ int err, prog_fd;
+ __u32 size;
+
+ err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector",
+ "jmp_table", &prog_fd);
+ if (err) {
+ error_cnt++;
+ return;
+ }
+
+ err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
+ &flow_keys, &size, &retval, &duration);
+ CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv4",
+ "err %d errno %d retval %d duration %d size %u/%lu\n",
+ err, errno, retval, duration, size, sizeof(flow_keys));
+ CHECK_FLOW_KEYS("ipv4_flow_keys", flow_keys, pkt_v4_flow_keys);
+
+ err = bpf_prog_test_run(prog_fd, 10, &pkt_v6, sizeof(pkt_v6),
+ &flow_keys, &size, &retval, &duration);
+ CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv6",
+ "err %d errno %d retval %d duration %d size %u/%lu\n",
+ err, errno, retval, duration, size, sizeof(flow_keys));
+ CHECK_FLOW_KEYS("ipv6_flow_keys", flow_keys, pkt_v6_flow_keys);
+
+ bpf_object__close(obj);
+ }
+
+ static void *test_spin_lock(void *arg)
+ {
+ __u32 duration, retval;
+ int err, prog_fd = *(u32 *) arg;
+
+ err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4),
+ NULL, NULL, &retval, &duration);
+ CHECK(err || retval, "",
+ "err %d errno %d retval %d duration %d\n",
+ err, errno, retval, duration);
+ pthread_exit(arg);
+ }
+
+ static void test_spinlock(void)
+ {
+ const char *file = "./test_spin_lock.o";
+ pthread_t thread_id[4];
+ struct bpf_object *obj;
+ int prog_fd;
+ int err = 0, i;
+ void *ret;
+
+ err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
+ if (err) {
+ printf("test_spin_lock:bpf_prog_load errno %d\n", errno);
+ goto close_prog;
+ }
+ for (i = 0; i < 4; i++)
+ assert(pthread_create(&thread_id[i], NULL,
+ &test_spin_lock, &prog_fd) == 0);
+ for (i = 0; i < 4; i++)
+ assert(pthread_join(thread_id[i], &ret) == 0 &&
+ ret == (void *)&prog_fd);
+ goto close_prog_noerr;
+ close_prog:
+ error_cnt++;
+ close_prog_noerr:
+ bpf_object__close(obj);
+ }
+
+ static void *parallel_map_access(void *arg)
+ {
+ int err, map_fd = *(u32 *) arg;
+ int vars[17], i, j, rnd, key = 0;
+
+ for (i = 0; i < 10000; i++) {
+ err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK);
+ if (err) {
+ printf("lookup failed\n");
+ error_cnt++;
+ goto out;
+ }
+ if (vars[0] != 0) {
+ printf("lookup #%d var[0]=%d\n", i, vars[0]);
+ error_cnt++;
+ goto out;
+ }
+ rnd = vars[1];
+ for (j = 2; j < 17; j++) {
+ if (vars[j] == rnd)
+ continue;
+ printf("lookup #%d var[1]=%d var[%d]=%d\n",
+ i, rnd, j, vars[j]);
+ error_cnt++;
+ goto out;
+ }
+ }
+ out:
+ pthread_exit(arg);
+ }
+
+ static void test_map_lock(void)
+ {
+ const char *file = "./test_map_lock.o";
+ int prog_fd, map_fd[2], vars[17] = {};
+ pthread_t thread_id[6];
+ struct bpf_object *obj;
+ int err = 0, key = 0, i;
+ void *ret;
+
+ err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
+ if (err) {
+ printf("test_map_lock:bpf_prog_load errno %d\n", errno);
+ goto close_prog;
+ }
+ map_fd[0] = bpf_find_map(__func__, obj, "hash_map");
+ if (map_fd[0] < 0)
+ goto close_prog;
+ map_fd[1] = bpf_find_map(__func__, obj, "array_map");
+ if (map_fd[1] < 0)
+ goto close_prog;
+
+ bpf_map_update_elem(map_fd[0], &key, vars, BPF_F_LOCK);
+
+ for (i = 0; i < 4; i++)
+ assert(pthread_create(&thread_id[i], NULL,
+ &test_spin_lock, &prog_fd) == 0);
+ for (i = 4; i < 6; i++)
+ assert(pthread_create(&thread_id[i], NULL,
+ ¶llel_map_access, &map_fd[i - 4]) == 0);
+ for (i = 0; i < 4; i++)
+ assert(pthread_join(thread_id[i], &ret) == 0 &&
+ ret == (void *)&prog_fd);
+ for (i = 4; i < 6; i++)
+ assert(pthread_join(thread_id[i], &ret) == 0 &&
+ ret == (void *)&map_fd[i - 4]);
+ goto close_prog_noerr;
+ close_prog:
+ error_cnt++;
+ close_prog_noerr:
+ bpf_object__close(obj);
+ }
+
int main(void)
{
srand(time(NULL));
@@@ -1982,7 -2135,9 +2178,10 @@@
test_reference_tracking();
test_queue_stack_map(QUEUE);
test_queue_stack_map(STACK);
+ test_signal_pending();
+ test_flow_dissector();
+ test_spinlock();
+ test_map_lock();
printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: linux-next: manual merge of the net-next tree with the bpf tree
From: Alexei Starovoitov @ 2019-02-20 0:41 UTC (permalink / raw)
To: Stephen Rothwell
Cc: David Miller, Networking, Daniel Borkmann, Alexei Starovoitov,
Linux Next Mailing List, Linux Kernel Mailing List,
Stanislav Fomichev
In-Reply-To: <20190220113729.49f28f73@canb.auug.org.au>
On Tue, Feb 19, 2019 at 4:37 PM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> Hi all,
>
> Today's linux-next merge of the net-next tree got a conflict in:
>
> tools/testing/selftests/bpf/test_progs.c
>
> between commit:
>
> f6be4d16039b ("selftests/bpf: make sure signal interrupts BPF_PROG_TEST_RUN")
Ouch. Thanks for the heads up.
Daniel,
should we drop this one from bpf tree ?
I don't think it's strictly necessary.
> from the bpf tree and commits:
>
> bf0f0fd93945 ("selftests/bpf: add simple BPF_PROG_TEST_RUN examples for flow dissector")
> ab963beb9f5d ("selftests/bpf: add bpf_spin_lock C test")
> ba72a7b4badb ("selftests/bpf: test for BPF_F_LOCK")
>
^ permalink raw reply
* Re: linux-next: manual merge of the net-next tree with the bpf tree
From: Stanislav Fomichev @ 2019-02-20 0:45 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Stephen Rothwell, David Miller, Networking, Daniel Borkmann,
Alexei Starovoitov, Linux Next Mailing List,
Linux Kernel Mailing List
In-Reply-To: <CAADnVQK3qg2k67LRiOqDmFnELrFOD1dLkrNbAvbMyu6xGpjBLw@mail.gmail.com>
On Tue, Feb 19, 2019 at 4:41 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Tue, Feb 19, 2019 at 4:37 PM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> >
> > Hi all,
> >
> > Today's linux-next merge of the net-next tree got a conflict in:
> >
> > tools/testing/selftests/bpf/test_progs.c
> >
> > between commit:
> >
> > f6be4d16039b ("selftests/bpf: make sure signal interrupts BPF_PROG_TEST_RUN")
>
> Ouch. Thanks for the heads up.
>
> Daniel,
> should we drop this one from bpf tree ?
> I don't think it's strictly necessary.
Yeah, those can go via the bpf-next three as well, not very critical.
OTOH, I don't understand why is there a conflict? bpf and bpf-next
adding tests in the same place/file? Those can be trivially resolved
when bpf and bpf-next are merged in the next window.
>
> > from the bpf tree and commits:
> >
> > bf0f0fd93945 ("selftests/bpf: add simple BPF_PROG_TEST_RUN examples for flow dissector")
> > ab963beb9f5d ("selftests/bpf: add bpf_spin_lock C test")
> > ba72a7b4badb ("selftests/bpf: test for BPF_F_LOCK")
> >
^ permalink raw reply
* Re: [PATCH net-next 3/3] nfp: devlink: allow flashing the device via devlink
From: Jakub Kicinski @ 2019-02-20 0:49 UTC (permalink / raw)
To: Jiri Pirko; +Cc: davem, netdev, oss-drivers, mkubecek, andrew
In-Reply-To: <20190219091942.GA3080@nanopsycho>
On Tue, 19 Feb 2019 10:19:42 +0100, Jiri Pirko wrote:
> Fri, Feb 15, 2019 at 04:44:29PM CET, jakub.kicinski@netronome.com wrote:
> >On Fri, 15 Feb 2019 11:15:14 +0100, Jiri Pirko wrote:
> >> > static const struct ethtool_ops nfp_net_ethtool_ops = {
> >>
> >> Why don't you use the compat fallback? I think you should.
> >
> >You and Michal both asked the same so let me answer the first to ask :)
> >- if devlink is built as a module the fallback is not reachable.
>
> So the fallback is not really good as you can't use it for real drivers
> anyway. Odd. Maybe we should compile devlink in without possibility to
> have it as module.
Ack, I'll make devlink a bool.
I need a little extra time, I forgot that nfp's flower offload still
doesn't register all ports (using your port flavour infrastructure).
^ permalink raw reply
* Re: linux-next: manual merge of the net-next tree with the bpf tree
From: Stephen Rothwell @ 2019-02-20 1:03 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Alexei Starovoitov, David Miller, Networking, Daniel Borkmann,
Alexei Starovoitov, Linux Next Mailing List,
Linux Kernel Mailing List
In-Reply-To: <CAKH8qBuoYKPMhHn6Xzo=nEBevBt93c4+9cAVW7BZZwpNj46SCA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 351 bytes --]
Hi Stanislav,
On Tue, 19 Feb 2019 16:45:46 -0800 Stanislav Fomichev <sdf@google.com> wrote:
>
> OTOH, I don't understand why is there a conflict? bpf and bpf-next
> adding tests in the same place/file? Those can be trivially resolved
> when bpf and bpf-next are merged in the next window.
Yes, and yes :-)
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: linux-next: manual merge of the net-next tree with the bpf tree
From: Daniel Borkmann @ 2019-02-20 0:48 UTC (permalink / raw)
To: Alexei Starovoitov, Stephen Rothwell
Cc: David Miller, Networking, Alexei Starovoitov,
Linux Next Mailing List, Linux Kernel Mailing List,
Stanislav Fomichev
In-Reply-To: <CAADnVQK3qg2k67LRiOqDmFnELrFOD1dLkrNbAvbMyu6xGpjBLw@mail.gmail.com>
On 02/20/2019 01:41 AM, Alexei Starovoitov wrote:
> On Tue, Feb 19, 2019 at 4:37 PM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>>
>> Hi all,
>>
>> Today's linux-next merge of the net-next tree got a conflict in:
>>
>> tools/testing/selftests/bpf/test_progs.c
>>
>> between commit:
>>
>> f6be4d16039b ("selftests/bpf: make sure signal interrupts BPF_PROG_TEST_RUN")
>
> Ouch. Thanks for the heads up.
>
> Daniel,
> should we drop this one from bpf tree ?
> I don't think it's strictly necessary.
Yeah no objections, lets move the selftest one over to bpf-next and
have it properly integrated. I think test_progs might potentially need
further topic-split aside from kernel progs like we did in test_verifier.
>> from the bpf tree and commits:
>>
>> bf0f0fd93945 ("selftests/bpf: add simple BPF_PROG_TEST_RUN examples for flow dissector")
>> ab963beb9f5d ("selftests/bpf: add bpf_spin_lock C test")
>> ba72a7b4badb ("selftests/bpf: test for BPF_F_LOCK")
^ permalink raw reply
* Questions about porting stmmac to a HI3535 SoC
From: Ed Martin @ 2019-02-20 1:58 UTC (permalink / raw)
To: netdev
Hi,
So I hope this is the right place to be asking this, this is my
first time doing real kernel development for something useful, and this
is long winded, I've spent a lot of time on it. Anyways, I am attempting
to make the stmmac driver work on a HiSilicon HI3535 SoC (this is a SoC
targeted at a Network video recorder application [arm cortex9 based]).
Anyways, I found a kernel on github that boots and the stmmac driver
works just fine, but it's a 3.4 kernel (link below). I've ported what I
could forward, but the stmmac driver includes support for TCP offload
and thus contains quite a bit of extra stuff, so for the stmmac driver
I've gone to adding support for the SoC. I did manage to find the
datasheet (in Chinese) for this chip, and nothing sticks out as
different. With it I added the clocks and device tree stuff, and the
driver mostly loads. The hardware appears to be dwmac1000/dwmac-3.610
(User ID: 0x10, Synopsys ID: 0x36), and from the other kernel, it also
includes a "CreVinn TOE-NK-2G TCP Offload Engine". I've for the most
part ported it, which has mostly been setting up the clocks for it
(which I think/hope I did right). Also of note, this device has two
GMACs one one controller (and they don't auto-detect right).
The kernel that I know works:
https://github.com/uyhoangtran/linux-kernel-3.4-hi3535
For my actual problem, I am testing it by attempting to netboot with NFS
over TCP, right now it comes up, sends out DHCP/configures the
interface, and then kind of works. By that I mean it sends out some
packets, but not all of the ones it should be sending actually go, it
mounts my server, and from my NFS server I see many TCP packets with it
communicating, and then it abruptly stops, and my server keeps
re-transmitting trying to get it back. Eventually I get the following error:
[ 244.050983] ------------[ cut here ]------------
[ 244.063088] WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:461
dev_watchdog+0x234/0x238
[ 244.084632] NETDEV WATCHDOG: eth0 (stmmaceth): transmit queue 0 timed out
[ 244.102332] CPU: 0 PID: 0 Comm: swapper Tainted: G W
4.19.0_hi3535-00055-g6218d4e6de03-dirty #455
[ 244.128833] Hardware name: Generic DT based system
<snip the backtrace>
My efforts to debug it has shown that adding a pr_warn() anywhere within
stmmac_xmit() mostly solves the problem (and it doesn't matter where in
that function, first line and last line results in the same thing). I
thought this indicates some sort of race problem, and I've tried placing
memory barriers all over that function and it does nothing. I've also
found out that this seems to happen when netdev_tx_sent_queue() is
called and it decides that the tx queue should be stopped. Then it seems
like the tx queue isn't restarted and I don't know why. Also it appears
that the next time stmmac_tx_clean() gets called it doesn't find all the
bytes that the previous stmmac_xmit() sent (usually one to three packets
short). I am basically out of ideas, other than switching to the latest
5.0 git branch, but I don't see anything that looks like it would fix
this (no major changes in the stmmac driver at least, I went though
every commit between the 4.19 and 5.0 and I don't see anything
important). I suppose I'll try it next.
So my two leading theories:
#1 sort of race with DMA transfers, but dma memory barriers before all
the important things already exist, and the driver already works on
other systems, so I assume it's ok, plus the old working driver didn't
make major changes with respect to these barriers (and I tried the
changes it did make)
#2 some sort of issue with how the netdev_* functions work, my
investigation showed the queue is stopped because the BQL queue runs
negative and there is a CONFIG_BQL option around all that code. But if
that was the cause, I'd expect other drivers to have a problem, and I
can find nothing on that issue. I can't seem to find where CONFIG_BQL is
enabled so I assume it's required.
So does anyone have any idea how I can debug this issue, I feel like
there is something obvious I'm missing, I can absolutely share
everything I have if someone wants to look through the changes I did
make, I just didn't get around to hosting it somewhere yet. Is there
something that's different about SoCs that I need to do.
^ permalink raw reply
* Re: [PATCH bpf-next 6/9] bpf: Sample program to load cg skb BPF programs
From: Jakub Kicinski @ 2019-02-20 2:14 UTC (permalink / raw)
To: brakmo; +Cc: netdev, Martin Lau, Alexei Starovoitov, daniel
In-Reply-To: <20190219053836.2086878-1-brakmo@fb.com>
On Mon, 18 Feb 2019 21:38:36 -0800, brakmo wrote:
> +#include "bpf_load.h"
nit: please use libbpf
^ permalink raw reply
* Re: [RFC PATCH net-next v3 05/21] ethtool: netlink bitset handling
From: Jakub Kicinski @ 2019-02-20 2:27 UTC (permalink / raw)
To: Michal Kubecek
Cc: netdev, David Miller, Andrew Lunn, Jiri Pirko, linux-kernel
In-Reply-To: <5f70eb8055a26f60f2282d7c1d193619a96c40a1.1550513384.git.mkubecek@suse.cz>
On Mon, 18 Feb 2019 19:21:49 +0100 (CET), Michal Kubecek wrote:
> + else if (is_u32)
> + bitmap_from_arr32(val, bitmap, nbits);
> + else
> + bitmap_copy(val, bitmap, nbits);
> + nla_for_each_nested(bit_attr, tb[ETHA_BITSET_BITS], rem) {
> + *err = ethnl_update_bit(val, mask, nbits, bit_attr,
> + is_list, names, legacy, info);
> + if (*err < 0)
> + goto out_free;
> + }
> + if (bitmask)
> + __bitmap_to_any(bitmask, mask, nbits, is_u32);
> + } else {
> + unsigned int change_words = DIV_ROUND_UP(change_bits, 32);
> +
> + *err = 0;
> + if (change_bits == 0 && tb[ETHA_BITSET_MASK])
> + goto out_free;
> + *err = -EINVAL;
> + if (!tb[ETHA_BITSET_VALUE])
> + goto out_free;
!tb[ETHA_BITSET_BITS] && !tb[ETHA_BITSET_VALUE] is already rejected
above.
> + if (nla_len(tb[ETHA_BITSET_VALUE]) < change_words * sizeof(u32))
> + goto out_free;
> + if (tb[ETHA_BITSET_MASK] &&
> + nla_len(tb[ETHA_BITSET_MASK]) < change_words * sizeof(u32))
> + goto out_free;
> +
> + bitmap_from_arr32(val, nla_data(tb[ETHA_BITSET_VALUE]),
> + change_bits);
> + if (tb[ETHA_BITSET_MASK])
> + bitmap_from_arr32(mask, nla_data(tb[ETHA_BITSET_MASK]),
> + change_bits);
> + else
> + bitmap_fill(mask, nbits);
> +
> + if (nbits < change_bits) {
> + unsigned int idx = find_next_bit(mask, max_bits, nbits);
> +
> + *err = -EINVAL;
> + if (idx < max_bits)
> + goto out_free;
> + }
^ permalink raw reply
* [Patch net-next 07/12] net: hns3: enable 8~11th bit of mac common msi-x error
From: Huazhong Tan @ 2019-02-20 2:32 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Weihang Li, Peng Li, Huazhong Tan
In-Reply-To: <1550629971-23999-1-git-send-email-tanhuazhong@huawei.com>
From: Weihang Li <liweihang@hisilicon.com>
These bits are enabled now and have been test.
Signed-off-by: Weihang Li <liweihang@hisilicon.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 6 ++++++
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h | 4 ++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
index 4951684..f0f1221 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
@@ -219,6 +219,12 @@ static const struct hclge_hw_error hclge_mac_afifo_tnl_int[] = {
{ .int_msk = BIT(5), .msg = "cge_igu_afifo_ecc_mbit_err" },
{ .int_msk = BIT(6), .msg = "lge_igu_afifo_ecc_1bit_err" },
{ .int_msk = BIT(7), .msg = "lge_igu_afifo_ecc_mbit_err" },
+ { .int_msk = BIT(8), .msg = "cge_igu_afifo_overflow_err" },
+ { .int_msk = BIT(9), .msg = "lge_igu_afifo_overflow_err" },
+ { .int_msk = BIT(10), .msg = "egu_cge_afifo_underrun_err" },
+ { .int_msk = BIT(11), .msg = "egu_lge_afifo_underrun_err" },
+ { .int_msk = BIT(12), .msg = "egu_ge_afifo_underrun_err" },
+ { .int_msk = BIT(13), .msg = "ge_igu_afifo_overflow_err" },
{ /* sentinel */ }
};
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
index 86d6143..fc06828 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
@@ -45,8 +45,8 @@
#define HCLGE_TM_QCN_MEM_ERR_INT_EN 0xFFFFFF
#define HCLGE_NCSI_ERR_INT_EN 0x3
#define HCLGE_NCSI_ERR_INT_TYPE 0x9
-#define HCLGE_MAC_COMMON_ERR_INT_EN GENMASK(7, 0)
-#define HCLGE_MAC_COMMON_ERR_INT_EN_MASK GENMASK(7, 0)
+#define HCLGE_MAC_COMMON_ERR_INT_EN 0x107FF
+#define HCLGE_MAC_COMMON_ERR_INT_EN_MASK 0x107FF
#define HCLGE_PPU_MPF_ABNORMAL_INT0_EN GENMASK(31, 0)
#define HCLGE_PPU_MPF_ABNORMAL_INT0_EN_MASK GENMASK(31, 0)
#define HCLGE_PPU_MPF_ABNORMAL_INT1_EN GENMASK(31, 0)
--
2.7.4
^ permalink raw reply related
* [Patch net-next 04/12] net: hns3: fix port info query issue for copper port
From: Huazhong Tan @ 2019-02-20 2:32 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Jian Shen, Peng Li, Huazhong Tan
In-Reply-To: <1550629971-23999-1-git-send-email-tanhuazhong@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
In original codes, for copper port which doesn't connect to phy,
it always returns -EOPNOTSUPP when query port information. This
patch fixes it by return the port information of MAC.
Fixes: 5f373b158523 ("net: hns3: Fix speed/duplex information loss problem when executing ethtool ethx cmd of VF")
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 9 +++--
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 38 +++++++++++++++++++---
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 4 +++
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 17 ++--------
4 files changed, 44 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 63f5f56..d94c90a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -621,12 +621,11 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
hns3_get_ksettings(h, cmd);
break;
case HNAE3_MEDIA_TYPE_COPPER:
- if (!netdev->phydev)
- return -EOPNOTSUPP;
-
cmd->base.port = PORT_TP;
- phy_ethtool_ksettings_get(netdev->phydev, cmd);
-
+ if (!netdev->phydev)
+ hns3_get_ksettings(h, cmd);
+ else
+ phy_ethtool_ksettings_get(netdev->phydev, cmd);
break;
default:
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 9a442f3..87edac4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -862,14 +862,44 @@ static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev,
linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
}
+static void hclge_parse_copper_link_mode(struct hclge_dev *hdev,
+ u8 speed_ability)
+{
+ unsigned long *supported = hdev->hw.mac.supported;
+
+ /* default to support all speed for GE port */
+ if (!speed_ability)
+ speed_ability = HCLGE_SUPPORT_GE;
+
+ if (speed_ability & HCLGE_SUPPORT_1G_BIT)
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ supported);
+
+ if (speed_ability & HCLGE_SUPPORT_100M_BIT) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ supported);
+ }
+
+ if (speed_ability & HCLGE_SUPPORT_10M_BIT) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, supported);
+ }
+
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
+}
+
static void hclge_parse_link_mode(struct hclge_dev *hdev, u8 speed_ability)
{
u8 media_type = hdev->hw.mac.media_type;
- if (media_type != HNAE3_MEDIA_TYPE_FIBER)
- return;
-
- hclge_parse_fiber_link_mode(hdev, speed_ability);
+ if (media_type == HNAE3_MEDIA_TYPE_FIBER)
+ hclge_parse_fiber_link_mode(hdev, speed_ability);
+ else if (media_type == HNAE3_MEDIA_TYPE_COPPER)
+ hclge_parse_copper_link_mode(hdev, speed_ability);
}
static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index c939f4a..3303919 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -188,6 +188,10 @@ enum HLCGE_PORT_TYPE {
#define HCLGE_SUPPORT_25G_BIT BIT(2)
#define HCLGE_SUPPORT_50G_BIT BIT(3)
#define HCLGE_SUPPORT_100G_BIT BIT(4)
+#define HCLGE_SUPPORT_100M_BIT BIT(6)
+#define HCLGE_SUPPORT_10M_BIT BIT(7)
+#define HCLGE_SUPPORT_GE \
+ (HCLGE_SUPPORT_1G_BIT | HCLGE_SUPPORT_100M_BIT | HCLGE_SUPPORT_10M_BIT)
enum HCLGE_DEV_STATE {
HCLGE_STATE_REINITING,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
index 84f2878..48eda2c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -8,12 +8,6 @@
#include "hclge_main.h"
#include "hclge_mdio.h"
-#define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \
- SUPPORTED_TP | \
- PHY_10BT_FEATURES | \
- PHY_100BT_FEATURES | \
- SUPPORTED_1000baseT_Full)
-
enum hclge_mdio_c22_op_seq {
HCLGE_MDIO_C22_WRITE = 1,
HCLGE_MDIO_C22_READ = 2
@@ -217,16 +211,9 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle)
return ret;
}
- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mask);
- linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, mask);
- linkmode_set_bit_array(phy_10_100_features_array,
- ARRAY_SIZE(phy_10_100_features_array),
- mask);
- linkmode_set_bit_array(phy_gbit_features_array,
- ARRAY_SIZE(phy_gbit_features_array),
- mask);
+ linkmode_copy(mask, hdev->hw.mac.supported);
linkmode_and(phydev->supported, phydev->supported, mask);
- phy_support_asym_pause(phydev);
+ linkmode_copy(phydev->advertising, phydev->supported);
return 0;
}
--
2.7.4
^ permalink raw reply related
* [Patch net-next 08/12] net: hns3: fix 6th bit of ppp mpf abnormal errors
From: Huazhong Tan @ 2019-02-20 2:32 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Weihang Li, Peng Li, Huazhong Tan
In-Reply-To: <1550629971-23999-1-git-send-email-tanhuazhong@huawei.com>
From: Weihang Li <liweihang@hisilicon.com>
This patch modify print message of 6th bit of ppp mpf abnormal errors,
there is a extra letter e in it.
Signed-off-by: Weihang Li <liweihang@hisilicon.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
index f0f1221..b9d363f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
@@ -80,7 +80,7 @@ static const struct hclge_hw_error hclge_ppp_mpf_abnormal_int_st1[] = {
{ .int_msk = BIT(3), .msg = "umv_key_mem1_ecc_mbit_err" },
{ .int_msk = BIT(4), .msg = "umv_key_mem2_ecc_mbit_err" },
{ .int_msk = BIT(5), .msg = "umv_key_mem3_ecc_mbit_err" },
- { .int_msk = BIT(6), .msg = "umv_ad_mem_ecc_mbit_erre" },
+ { .int_msk = BIT(6), .msg = "umv_ad_mem_ecc_mbit_err" },
{ .int_msk = BIT(7), .msg = "rss_tc_mode_mem_ecc_mbit_err" },
{ .int_msk = BIT(8), .msg = "rss_idt_mem0_ecc_mbit_err" },
{ .int_msk = BIT(9), .msg = "rss_idt_mem1_ecc_mbit_err" },
--
2.7.4
^ permalink raw reply related
* [Patch net-next 12/12] net: hns3: clear command queue's registers when unloading VF driver
From: Huazhong Tan @ 2019-02-20 2:32 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Huazhong Tan, Peng Li
In-Reply-To: <1550629971-23999-1-git-send-email-tanhuazhong@huawei.com>
According to the hardware's description, the driver should clear
the command queue's registers when uloading VF driver. Otherwise,
these existing value may lead the IMP get into a wrong state.
Fixes: fedd0c15d288 ("net: hns3: Add HNS3 VF IMP(Integrated Management Proc) cmd interface")
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
index 4e78e88..9441b45 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
@@ -362,8 +362,28 @@ int hclgevf_cmd_init(struct hclgevf_dev *hdev)
return 0;
}
+static void hclgevf_cmd_uninit_regs(struct hclgevf_hw *hw)
+{
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_L_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_H_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_HEAD_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_TAIL_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_L_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_H_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_DEPTH_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_HEAD_REG, 0);
+ hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_TAIL_REG, 0);
+}
+
void hclgevf_cmd_uninit(struct hclgevf_dev *hdev)
{
+ spin_lock_bh(&hdev->hw.cmq.csq.lock);
+ spin_lock(&hdev->hw.cmq.crq.lock);
+ clear_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
+ hclgevf_cmd_uninit_regs(&hdev->hw);
+ spin_unlock(&hdev->hw.cmq.crq.lock);
+ spin_unlock_bh(&hdev->hw.cmq.csq.lock);
hclgevf_free_cmd_desc(&hdev->hw.cmq.csq);
hclgevf_free_cmd_desc(&hdev->hw.cmq.crq);
}
--
2.7.4
^ permalink raw reply related
* [Patch net-next 00/12] code optimizations & bugfixes for HNS3 driver
From: Huazhong Tan @ 2019-02-20 2:32 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Huazhong Tan
This patchset includes bugfixes and code optimizations for
the HNS3 ethernet controller driver.
Huazhong Tan (2):
net: hns3: uninitialize command queue while unloading PF driver
net: hns3: clear command queue's registers when unloading VF driver
Jian Shen (2):
net: hns3: convert mac advertize and supported from u32 to link mode
net: hns3: fix port info query issue for copper port
Weihang Li (4):
net: hns3: modify print message of ssu common ecc errors
net: hns3: some bugfix of ppu(rcb) ras errors
net: hns3: enable 8~11th bit of mac common msi-x error
net: hns3: fix 6th bit of ppp mpf abnormal errors
Yonglong Liu (2):
net: hns3: add pointer checking at the beginning of the exported
functions.
net: hns3: Check variable is valid before assigning it to another
liuzhongzhu (2):
net: hns3: Record VF unicast and multicast tables
net: hns3: Record VF vlan tables
drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h | 2 +
drivers/net/ethernet/hisilicon/hns3/hnae3.c | 37 ++-
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 9 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 26 +++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 69 +++++-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h | 5 +-
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 248 +++++++++++++++++++--
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 40 ++++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 32 ++-
.../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 17 +-
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 20 ++
12 files changed, 451 insertions(+), 56 deletions(-)
--
2.7.4
^ permalink raw reply
* [Patch net-next 03/12] net: hns3: convert mac advertize and supported from u32 to link mode
From: Huazhong Tan @ 2019-02-20 2:32 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Jian Shen, Peng Li, Huazhong Tan
In-Reply-To: <1550629971-23999-1-git-send-email-tanhuazhong@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
The link mode with bits has been up to more than 31 for some MAC
and phy. Convert to using a linkmode bitmap, which can support all
link modes.
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 24 +++++++++++-----------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 75ec309..9a442f3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -839,27 +839,27 @@ static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev,
unsigned long *supported = hdev->hw.mac.supported;
if (speed_ability & HCLGE_SUPPORT_1G_BIT)
- set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_10G_BIT)
- set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_25G_BIT)
- set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_50G_BIT)
- set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+ supported);
if (speed_ability & HCLGE_SUPPORT_100G_BIT)
- set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
- supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+ supported);
- set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
- set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
}
static void hclge_parse_link_mode(struct hclge_dev *hdev, u8 speed_ability)
--
2.7.4
^ permalink raw reply related
* [Patch net-next 09/12] net: hns3: Record VF unicast and multicast tables
From: Huazhong Tan @ 2019-02-20 2:32 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
liuzhongzhu, Peng Li, Huazhong Tan
In-Reply-To: <1550629971-23999-1-git-send-email-tanhuazhong@huawei.com>
From: liuzhongzhu <liuzhongzhu@huawei.com>
Record the unicast and multicast tables that the VF sends to the chip.
After the VF exception, the PF actively clears the VF to chip config.
Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h | 2 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 102 +++++++++++++++++++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 25 +++++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 28 +++++-
4 files changed, 156 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
index 53089cd..9b6b7b4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
@@ -42,6 +42,8 @@ enum HCLGE_MBX_OPCODE {
HCLGE_MBX_GET_QID_IN_PF, /* (VF -> PF) get queue id in pf */
HCLGE_MBX_LINK_STAT_MODE, /* (PF -> VF) link mode has changed */
HCLGE_MBX_GET_LINK_MODE, /* (VF -> PF) get the link mode of pf */
+
+ HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
};
/* below are per-VF mac-vlan subcodes */
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 87edac4..b1f5c6f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1329,6 +1329,8 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
vport->back = hdev;
vport->vport_id = i;
vport->mps = HCLGE_MAC_DEFAULT_FRAME;
+ INIT_LIST_HEAD(&vport->uc_mac_list);
+ INIT_LIST_HEAD(&vport->mc_mac_list);
if (i == 0)
ret = hclge_vport_setup(vport, tqp_main_vport);
@@ -6074,6 +6076,103 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
return status;
}
+void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+ struct hclge_vport_mac_addr_cfg *mac_cfg;
+ struct list_head *list;
+
+ if (!vport->vport_id)
+ return;
+
+ mac_cfg = kzalloc(sizeof(*mac_cfg), GFP_KERNEL);
+ if (!mac_cfg)
+ return;
+
+ mac_cfg->hd_tbl_status = true;
+ memcpy(mac_cfg->mac_addr, mac_addr, ETH_ALEN);
+
+ list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+ &vport->uc_mac_list : &vport->mc_mac_list;
+
+ list_add_tail(&mac_cfg->node, list);
+}
+
+void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ bool is_write_tbl,
+ enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+ struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp;
+ struct list_head *list;
+ bool uc_flag, mc_flag;
+
+ list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+ &vport->uc_mac_list : &vport->mc_mac_list;
+
+ uc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_UC;
+ mc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_MC;
+
+ list_for_each_entry_safe(mac_cfg, tmp, list, node) {
+ if (strncmp(mac_cfg->mac_addr, mac_addr, ETH_ALEN) == 0) {
+ if (uc_flag && mac_cfg->hd_tbl_status)
+ hclge_rm_uc_addr_common(vport, mac_addr);
+
+ if (mc_flag && mac_cfg->hd_tbl_status)
+ hclge_rm_mc_addr_common(vport, mac_addr);
+
+ list_del(&mac_cfg->node);
+ kfree(mac_cfg);
+ break;
+ }
+ }
+}
+
+void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
+ enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+ struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp;
+ struct list_head *list;
+
+ list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+ &vport->uc_mac_list : &vport->mc_mac_list;
+
+ list_for_each_entry_safe(mac_cfg, tmp, list, node) {
+ if (mac_type == HCLGE_MAC_ADDR_UC && mac_cfg->hd_tbl_status)
+ hclge_rm_uc_addr_common(vport, mac_cfg->mac_addr);
+
+ if (mac_type == HCLGE_MAC_ADDR_MC && mac_cfg->hd_tbl_status)
+ hclge_rm_mc_addr_common(vport, mac_cfg->mac_addr);
+
+ mac_cfg->hd_tbl_status = false;
+ if (is_del_list) {
+ list_del(&mac_cfg->node);
+ kfree(mac_cfg);
+ }
+ }
+}
+
+void hclge_uninit_vport_mac_table(struct hclge_dev *hdev)
+{
+ struct hclge_vport_mac_addr_cfg *mac, *tmp;
+ struct hclge_vport *vport;
+ int i;
+
+ mutex_lock(&hdev->vport_cfg_mutex);
+ for (i = 0; i < hdev->num_alloc_vport; i++) {
+ vport = &hdev->vport[i];
+ list_for_each_entry_safe(mac, tmp, &vport->uc_mac_list, node) {
+ list_del(&mac->node);
+ kfree(mac);
+ }
+
+ list_for_each_entry_safe(mac, tmp, &vport->mc_mac_list, node) {
+ list_del(&mac->node);
+ kfree(mac);
+ }
+ }
+ mutex_unlock(&hdev->vport_cfg_mutex);
+}
+
static int hclge_get_mac_ethertype_cmd_status(struct hclge_dev *hdev,
u16 cmdq_resp, u8 resp_code)
{
@@ -7329,6 +7428,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
hdev->mps = ETH_FRAME_LEN + ETH_FCS_LEN + 2 * VLAN_HLEN;
mutex_init(&hdev->vport_lock);
+ mutex_init(&hdev->vport_cfg_mutex);
ret = hclge_pci_init(hdev);
if (ret) {
@@ -7621,6 +7721,8 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
hclge_misc_irq_uninit(hdev);
hclge_pci_uninit(hdev);
mutex_destroy(&hdev->vport_lock);
+ hclge_uninit_vport_mac_table(hdev);
+ mutex_destroy(&hdev->vport_cfg_mutex);
ae_dev->priv = NULL;
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 3303919..781bd11 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -632,6 +632,17 @@ struct hclge_fd_ad_data {
u16 rule_id;
};
+struct hclge_vport_mac_addr_cfg {
+ struct list_head node;
+ int hd_tbl_status;
+ u8 mac_addr[ETH_ALEN];
+};
+
+enum HCLGE_MAC_ADDR_TYPE {
+ HCLGE_MAC_ADDR_UC,
+ HCLGE_MAC_ADDR_MC
+};
+
/* For each bit of TCAM entry, it uses a pair of 'x' and
* 'y' to indicate which value to match, like below:
* ----------------------------------
@@ -771,6 +782,8 @@ struct hclge_dev {
/* unicast mac vlan space shared by PF and its VFs */
u16 share_umv_size;
struct mutex umv_mutex; /* protect share_umv_size */
+
+ struct mutex vport_cfg_mutex; /* Protect stored vf table */
};
/* VPort level vlan tag configuration for TX direction */
@@ -838,6 +851,9 @@ struct hclge_vport {
unsigned long state;
unsigned long last_active_jiffies;
u32 mps; /* Max packet size */
+
+ struct list_head uc_mac_list; /* Store VF unicast table */
+ struct list_head mc_mac_list; /* Store VF multicast table */
};
void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
@@ -892,4 +908,13 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf);
u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id);
int hclge_notify_client(struct hclge_dev *hdev,
enum hnae3_reset_notify_type type);
+void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ enum HCLGE_MAC_ADDR_TYPE mac_type);
+void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+ bool is_write_tbl,
+ enum HCLGE_MAC_ADDR_TYPE mac_type);
+void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
+ enum HCLGE_MAC_ADDR_TYPE mac_type);
+void hclge_uninit_vport_mac_table(struct hclge_dev *hdev);
+
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
index 7e4a104..476ca83 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
@@ -224,12 +224,24 @@ static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport,
hclge_rm_uc_addr_common(vport, old_addr);
status = hclge_add_uc_addr_common(vport, mac_addr);
- if (status)
+ if (status) {
hclge_add_uc_addr_common(vport, old_addr);
+ } else {
+ hclge_rm_vport_mac_table(vport, mac_addr,
+ false, HCLGE_MAC_ADDR_UC);
+ hclge_add_vport_mac_table(vport, mac_addr,
+ HCLGE_MAC_ADDR_UC);
+ }
} else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_ADD) {
status = hclge_add_uc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_add_vport_mac_table(vport, mac_addr,
+ HCLGE_MAC_ADDR_UC);
} else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_REMOVE) {
status = hclge_rm_uc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_rm_vport_mac_table(vport, mac_addr,
+ false, HCLGE_MAC_ADDR_UC);
} else {
dev_err(&hdev->pdev->dev,
"failed to set unicast mac addr, unknown subcode %d\n",
@@ -255,8 +267,14 @@ static int hclge_set_vf_mc_mac_addr(struct hclge_vport *vport,
if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_ADD) {
status = hclge_add_mc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_add_vport_mac_table(vport, mac_addr,
+ HCLGE_MAC_ADDR_MC);
} else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_REMOVE) {
status = hclge_rm_mc_addr_common(vport, mac_addr);
+ if (!status)
+ hclge_rm_vport_mac_table(vport, mac_addr,
+ false, HCLGE_MAC_ADDR_MC);
} else {
dev_err(&hdev->pdev->dev,
"failed to set mcast mac addr, unknown subcode %d\n",
@@ -585,6 +603,14 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
case HCLGE_MBX_GET_LINK_MODE:
hclge_get_link_mode(vport, req);
break;
+ case HCLGE_MBX_GET_VF_FLR_STATUS:
+ mutex_lock(&hdev->vport_cfg_mutex);
+ hclge_rm_vport_all_mac_table(vport, true,
+ HCLGE_MAC_ADDR_UC);
+ hclge_rm_vport_all_mac_table(vport, true,
+ HCLGE_MAC_ADDR_MC);
+ mutex_unlock(&hdev->vport_cfg_mutex);
+ break;
default:
dev_err(&hdev->pdev->dev,
"un-supported mailbox message, code = %d\n",
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox