Merge e918c7bbc0 ("Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue") into android-mainline
Steps on the way to 6.10-rc1 Change-Id: Ia4c1e5f35e0d6caa322300de89778b07da97a631 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -1670,11 +1670,13 @@ static void gswip_port_set_pause(struct gswip_priv *priv, int port,
|
||||
mdio_phy, GSWIP_MDIO_PHYp(port));
|
||||
}
|
||||
|
||||
static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
static void gswip_phylink_mac_config(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct gswip_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct gswip_priv *priv = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
u32 miicfg = 0;
|
||||
|
||||
miicfg |= GSWIP_MII_CFG_LDCLKDIS;
|
||||
@@ -1700,7 +1702,7 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
miicfg |= GSWIP_MII_CFG_MODE_GMII;
|
||||
break;
|
||||
default:
|
||||
dev_err(ds->dev,
|
||||
dev_err(dp->ds->dev,
|
||||
"Unsupported interface: %d\n", state->interface);
|
||||
return;
|
||||
}
|
||||
@@ -1726,28 +1728,32 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
}
|
||||
}
|
||||
|
||||
static void gswip_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
static void gswip_phylink_mac_link_down(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct gswip_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct gswip_priv *priv = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
|
||||
gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, port);
|
||||
|
||||
if (!dsa_is_cpu_port(ds, port))
|
||||
if (!dsa_port_is_cpu(dp))
|
||||
gswip_port_set_link(priv, port, false);
|
||||
}
|
||||
|
||||
static void gswip_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
static void gswip_phylink_mac_link_up(struct phylink_config *config,
|
||||
struct phy_device *phydev,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface,
|
||||
struct phy_device *phydev,
|
||||
int speed, int duplex,
|
||||
bool tx_pause, bool rx_pause)
|
||||
{
|
||||
struct gswip_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct gswip_priv *priv = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
|
||||
if (!dsa_is_cpu_port(ds, port)) {
|
||||
if (!dsa_port_is_cpu(dp)) {
|
||||
gswip_port_set_link(priv, port, true);
|
||||
gswip_port_set_speed(priv, port, speed, interface);
|
||||
gswip_port_set_duplex(priv, port, duplex);
|
||||
@@ -1824,6 +1830,12 @@ static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset)
|
||||
return ARRAY_SIZE(gswip_rmon_cnt);
|
||||
}
|
||||
|
||||
static const struct phylink_mac_ops gswip_phylink_mac_ops = {
|
||||
.mac_config = gswip_phylink_mac_config,
|
||||
.mac_link_down = gswip_phylink_mac_link_down,
|
||||
.mac_link_up = gswip_phylink_mac_link_up,
|
||||
};
|
||||
|
||||
static const struct dsa_switch_ops gswip_xrx200_switch_ops = {
|
||||
.get_tag_protocol = gswip_get_tag_protocol,
|
||||
.setup = gswip_setup,
|
||||
@@ -1842,9 +1854,6 @@ static const struct dsa_switch_ops gswip_xrx200_switch_ops = {
|
||||
.port_change_mtu = gswip_port_change_mtu,
|
||||
.port_max_mtu = gswip_port_max_mtu,
|
||||
.phylink_get_caps = gswip_xrx200_phylink_get_caps,
|
||||
.phylink_mac_config = gswip_phylink_mac_config,
|
||||
.phylink_mac_link_down = gswip_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = gswip_phylink_mac_link_up,
|
||||
.get_strings = gswip_get_strings,
|
||||
.get_ethtool_stats = gswip_get_ethtool_stats,
|
||||
.get_sset_count = gswip_get_sset_count,
|
||||
@@ -1868,9 +1877,6 @@ static const struct dsa_switch_ops gswip_xrx300_switch_ops = {
|
||||
.port_change_mtu = gswip_port_change_mtu,
|
||||
.port_max_mtu = gswip_port_max_mtu,
|
||||
.phylink_get_caps = gswip_xrx300_phylink_get_caps,
|
||||
.phylink_mac_config = gswip_phylink_mac_config,
|
||||
.phylink_mac_link_down = gswip_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = gswip_phylink_mac_link_up,
|
||||
.get_strings = gswip_get_strings,
|
||||
.get_ethtool_stats = gswip_get_ethtool_stats,
|
||||
.get_sset_count = gswip_get_sset_count,
|
||||
@@ -2136,6 +2142,7 @@ static int gswip_probe(struct platform_device *pdev)
|
||||
priv->ds->num_ports = priv->hw_info->max_ports;
|
||||
priv->ds->priv = priv;
|
||||
priv->ds->ops = priv->hw_info->ops;
|
||||
priv->ds->phylink_mac_ops = &gswip_phylink_mac_ops;
|
||||
priv->dev = dev;
|
||||
mutex_init(&priv->pce_table_lock);
|
||||
version = gswip_switch_r(priv, GSWIP_VERSION);
|
||||
|
||||
+29
-17
@@ -2858,28 +2858,34 @@ mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
}
|
||||
|
||||
static struct phylink_pcs *
|
||||
mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port,
|
||||
mt753x_phylink_mac_select_pcs(struct phylink_config *config,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mt7530_priv *priv = dp->ds->priv;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_TRGMII:
|
||||
return &priv->pcs[port].pcs;
|
||||
return &priv->pcs[dp->index].pcs;
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
return priv->ports[port].sgmii_pcs;
|
||||
return priv->ports[dp->index].sgmii_pcs;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
mt753x_phylink_mac_config(struct phylink_config *config, unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
struct mt7530_priv *priv;
|
||||
int port = dp->index;
|
||||
|
||||
priv = ds->priv;
|
||||
|
||||
if ((port == 5 || port == 6) && priv->info->mac_port_config)
|
||||
priv->info->mac_port_config(ds, port, mode, state->interface);
|
||||
@@ -2889,23 +2895,25 @@ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY);
|
||||
}
|
||||
|
||||
static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
static void mt753x_phylink_mac_link_down(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mt7530_priv *priv = dp->ds->priv;
|
||||
|
||||
mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
|
||||
mt7530_clear(priv, MT7530_PMCR_P(dp->index), PMCR_LINK_SETTINGS_MASK);
|
||||
}
|
||||
|
||||
static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
static void mt753x_phylink_mac_link_up(struct phylink_config *config,
|
||||
struct phy_device *phydev,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface,
|
||||
struct phy_device *phydev,
|
||||
int speed, int duplex,
|
||||
bool tx_pause, bool rx_pause)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mt7530_priv *priv = dp->ds->priv;
|
||||
u32 mcr;
|
||||
|
||||
mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
|
||||
@@ -2940,7 +2948,7 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
}
|
||||
}
|
||||
|
||||
mt7530_set(priv, MT7530_PMCR_P(port), mcr);
|
||||
mt7530_set(priv, MT7530_PMCR_P(dp->index), mcr);
|
||||
}
|
||||
|
||||
static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
@@ -3160,16 +3168,19 @@ const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.port_mirror_add = mt753x_port_mirror_add,
|
||||
.port_mirror_del = mt753x_port_mirror_del,
|
||||
.phylink_get_caps = mt753x_phylink_get_caps,
|
||||
.phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs,
|
||||
.phylink_mac_config = mt753x_phylink_mac_config,
|
||||
.phylink_mac_link_down = mt753x_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = mt753x_phylink_mac_link_up,
|
||||
.get_mac_eee = mt753x_get_mac_eee,
|
||||
.set_mac_eee = mt753x_set_mac_eee,
|
||||
.conduit_state_change = mt753x_conduit_state_change,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt7530_switch_ops);
|
||||
|
||||
static const struct phylink_mac_ops mt753x_phylink_mac_ops = {
|
||||
.mac_select_pcs = mt753x_phylink_mac_select_pcs,
|
||||
.mac_config = mt753x_phylink_mac_config,
|
||||
.mac_link_down = mt753x_phylink_mac_link_down,
|
||||
.mac_link_up = mt753x_phylink_mac_link_up,
|
||||
};
|
||||
|
||||
const struct mt753x_info mt753x_table[] = {
|
||||
[ID_MT7621] = {
|
||||
.id = ID_MT7621,
|
||||
@@ -3247,6 +3258,7 @@ mt7530_probe_common(struct mt7530_priv *priv)
|
||||
priv->dev = dev;
|
||||
priv->ds->priv = priv;
|
||||
priv->ds->ops = &mt7530_switch_ops;
|
||||
priv->ds->phylink_mac_ops = &mt753x_phylink_mac_ops;
|
||||
mutex_init(&priv->reg_mutex);
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
|
||||
@@ -523,28 +523,30 @@ static void ar9331_sw_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9331_sw_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
static void ar9331_sw_phylink_mac_config(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct ar9331_sw_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct ar9331_sw_priv *priv = dp->ds->priv;
|
||||
struct regmap *regmap = priv->regmap;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_STATUS(port),
|
||||
ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_STATUS(dp->index),
|
||||
AR9331_SW_PORT_STATUS_LINK_EN |
|
||||
AR9331_SW_PORT_STATUS_FLOW_LINK_EN, 0);
|
||||
if (ret)
|
||||
dev_err_ratelimited(priv->dev, "%s: %i\n", __func__, ret);
|
||||
}
|
||||
|
||||
static void ar9331_sw_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
static void ar9331_sw_phylink_mac_link_down(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct ar9331_sw_priv *priv = ds->priv;
|
||||
struct ar9331_sw_port *p = &priv->port[port];
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct ar9331_sw_priv *priv = dp->ds->priv;
|
||||
struct regmap *regmap = priv->regmap;
|
||||
int port = dp->index;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_STATUS(port),
|
||||
@@ -552,23 +554,24 @@ static void ar9331_sw_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
if (ret)
|
||||
dev_err_ratelimited(priv->dev, "%s: %i\n", __func__, ret);
|
||||
|
||||
cancel_delayed_work_sync(&p->mib_read);
|
||||
cancel_delayed_work_sync(&priv->port[port].mib_read);
|
||||
}
|
||||
|
||||
static void ar9331_sw_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
static void ar9331_sw_phylink_mac_link_up(struct phylink_config *config,
|
||||
struct phy_device *phydev,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface,
|
||||
struct phy_device *phydev,
|
||||
int speed, int duplex,
|
||||
bool tx_pause, bool rx_pause)
|
||||
{
|
||||
struct ar9331_sw_priv *priv = ds->priv;
|
||||
struct ar9331_sw_port *p = &priv->port[port];
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct ar9331_sw_priv *priv = dp->ds->priv;
|
||||
struct regmap *regmap = priv->regmap;
|
||||
int port = dp->index;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
schedule_delayed_work(&p->mib_read, 0);
|
||||
schedule_delayed_work(&priv->port[port].mib_read, 0);
|
||||
|
||||
val = AR9331_SW_PORT_STATUS_MAC_MASK;
|
||||
switch (speed) {
|
||||
@@ -684,14 +687,17 @@ static void ar9331_get_pause_stats(struct dsa_switch *ds, int port,
|
||||
spin_unlock(&p->stats_lock);
|
||||
}
|
||||
|
||||
static const struct phylink_mac_ops ar9331_phylink_mac_ops = {
|
||||
.mac_config = ar9331_sw_phylink_mac_config,
|
||||
.mac_link_down = ar9331_sw_phylink_mac_link_down,
|
||||
.mac_link_up = ar9331_sw_phylink_mac_link_up,
|
||||
};
|
||||
|
||||
static const struct dsa_switch_ops ar9331_sw_ops = {
|
||||
.get_tag_protocol = ar9331_sw_get_tag_protocol,
|
||||
.setup = ar9331_sw_setup,
|
||||
.port_disable = ar9331_sw_port_disable,
|
||||
.phylink_get_caps = ar9331_sw_phylink_get_caps,
|
||||
.phylink_mac_config = ar9331_sw_phylink_mac_config,
|
||||
.phylink_mac_link_down = ar9331_sw_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = ar9331_sw_phylink_mac_link_up,
|
||||
.get_stats64 = ar9331_get_stats64,
|
||||
.get_pause_stats = ar9331_get_pause_stats,
|
||||
};
|
||||
@@ -1059,6 +1065,7 @@ static int ar9331_sw_probe(struct mdio_device *mdiodev)
|
||||
ds->priv = priv;
|
||||
priv->ops = ar9331_sw_ops;
|
||||
ds->ops = &priv->ops;
|
||||
ds->phylink_mac_ops = &ar9331_phylink_mac_ops;
|
||||
dev_set_drvdata(&mdiodev->dev, priv);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->port); i++) {
|
||||
|
||||
@@ -1283,11 +1283,13 @@ qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_inde
|
||||
}
|
||||
|
||||
static struct phylink_pcs *
|
||||
qca8k_phylink_mac_select_pcs(struct dsa_switch *ds, int port,
|
||||
qca8k_phylink_mac_select_pcs(struct phylink_config *config,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct qca8k_priv *priv = dp->ds->priv;
|
||||
struct phylink_pcs *pcs = NULL;
|
||||
int port = dp->index;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
@@ -1311,13 +1313,18 @@ qca8k_phylink_mac_select_pcs(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
static void
|
||||
qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
qca8k_phylink_mac_config(struct phylink_config *config, unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
struct qca8k_priv *priv;
|
||||
int port = dp->index;
|
||||
int cpu_port_index;
|
||||
u32 reg;
|
||||
|
||||
priv = ds->priv;
|
||||
|
||||
switch (port) {
|
||||
case 0: /* 1st CPU port */
|
||||
if (state->interface != PHY_INTERFACE_MODE_RGMII &&
|
||||
@@ -1426,20 +1433,24 @@ static void qca8k_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
static void
|
||||
qca8k_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
qca8k_phylink_mac_link_down(struct phylink_config *config, unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct qca8k_priv *priv = dp->ds->priv;
|
||||
|
||||
qca8k_port_set_status(priv, port, 0);
|
||||
qca8k_port_set_status(priv, dp->index, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
phy_interface_t interface, struct phy_device *phydev,
|
||||
int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||
qca8k_phylink_mac_link_up(struct phylink_config *config,
|
||||
struct phy_device *phydev, unsigned int mode,
|
||||
phy_interface_t interface, int speed, int duplex,
|
||||
bool tx_pause, bool rx_pause)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct qca8k_priv *priv = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
u32 reg;
|
||||
|
||||
if (phylink_autoneg_inband(mode)) {
|
||||
@@ -1463,10 +1474,10 @@ qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
if (duplex == DUPLEX_FULL)
|
||||
reg |= QCA8K_PORT_STATUS_DUPLEX;
|
||||
|
||||
if (rx_pause || dsa_is_cpu_port(ds, port))
|
||||
if (rx_pause || dsa_port_is_cpu(dp))
|
||||
reg |= QCA8K_PORT_STATUS_RXFLOW;
|
||||
|
||||
if (tx_pause || dsa_is_cpu_port(ds, port))
|
||||
if (tx_pause || dsa_port_is_cpu(dp))
|
||||
reg |= QCA8K_PORT_STATUS_TXFLOW;
|
||||
}
|
||||
|
||||
@@ -1991,6 +2002,13 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phylink_mac_ops qca8k_phylink_mac_ops = {
|
||||
.mac_select_pcs = qca8k_phylink_mac_select_pcs,
|
||||
.mac_config = qca8k_phylink_mac_config,
|
||||
.mac_link_down = qca8k_phylink_mac_link_down,
|
||||
.mac_link_up = qca8k_phylink_mac_link_up,
|
||||
};
|
||||
|
||||
static const struct dsa_switch_ops qca8k_switch_ops = {
|
||||
.get_tag_protocol = qca8k_get_tag_protocol,
|
||||
.setup = qca8k_setup,
|
||||
@@ -2021,10 +2039,6 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
|
||||
.port_vlan_add = qca8k_port_vlan_add,
|
||||
.port_vlan_del = qca8k_port_vlan_del,
|
||||
.phylink_get_caps = qca8k_phylink_get_caps,
|
||||
.phylink_mac_select_pcs = qca8k_phylink_mac_select_pcs,
|
||||
.phylink_mac_config = qca8k_phylink_mac_config,
|
||||
.phylink_mac_link_down = qca8k_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = qca8k_phylink_mac_link_up,
|
||||
.get_phy_flags = qca8k_get_phy_flags,
|
||||
.port_lag_join = qca8k_port_lag_join,
|
||||
.port_lag_leave = qca8k_port_lag_leave,
|
||||
@@ -2091,6 +2105,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
|
||||
priv->ds->num_ports = QCA8K_NUM_PORTS;
|
||||
priv->ds->priv = priv;
|
||||
priv->ds->ops = &qca8k_switch_ops;
|
||||
priv->ds->phylink_mac_ops = &qca8k_phylink_mac_ops;
|
||||
mutex_init(&priv->reg_mutex);
|
||||
dev_set_drvdata(&mdiodev->dev, priv);
|
||||
|
||||
|
||||
@@ -1358,10 +1358,11 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
|
||||
}
|
||||
|
||||
static struct phylink_pcs *
|
||||
sja1105_mac_select_pcs(struct dsa_switch *ds, int port, phy_interface_t iface)
|
||||
sja1105_mac_select_pcs(struct phylink_config *config, phy_interface_t iface)
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct dw_xpcs *xpcs = priv->xpcs[port];
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct sja1105_private *priv = dp->ds->priv;
|
||||
struct dw_xpcs *xpcs = priv->xpcs[dp->index];
|
||||
|
||||
if (xpcs)
|
||||
return &xpcs->pcs;
|
||||
@@ -1369,21 +1370,31 @@ sja1105_mac_select_pcs(struct dsa_switch *ds, int port, phy_interface_t iface)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sja1105_mac_link_down(struct dsa_switch *ds, int port,
|
||||
static void sja1105_mac_config(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
}
|
||||
|
||||
static void sja1105_mac_link_down(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
sja1105_inhibit_tx(ds->priv, BIT(port), true);
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
|
||||
sja1105_inhibit_tx(dp->ds->priv, BIT(dp->index), true);
|
||||
}
|
||||
|
||||
static void sja1105_mac_link_up(struct dsa_switch *ds, int port,
|
||||
static void sja1105_mac_link_up(struct phylink_config *config,
|
||||
struct phy_device *phydev,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface,
|
||||
struct phy_device *phydev,
|
||||
int speed, int duplex,
|
||||
bool tx_pause, bool rx_pause)
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct sja1105_private *priv = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
|
||||
sja1105_adjust_port_config(priv, port, speed);
|
||||
|
||||
@@ -3198,6 +3209,13 @@ static void sja1105_teardown(struct dsa_switch *ds)
|
||||
sja1105_static_config_free(&priv->static_config);
|
||||
}
|
||||
|
||||
static const struct phylink_mac_ops sja1105_phylink_mac_ops = {
|
||||
.mac_select_pcs = sja1105_mac_select_pcs,
|
||||
.mac_config = sja1105_mac_config,
|
||||
.mac_link_up = sja1105_mac_link_up,
|
||||
.mac_link_down = sja1105_mac_link_down,
|
||||
};
|
||||
|
||||
static const struct dsa_switch_ops sja1105_switch_ops = {
|
||||
.get_tag_protocol = sja1105_get_tag_protocol,
|
||||
.connect_tag_protocol = sja1105_connect_tag_protocol,
|
||||
@@ -3207,9 +3225,6 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
|
||||
.port_change_mtu = sja1105_change_mtu,
|
||||
.port_max_mtu = sja1105_get_max_mtu,
|
||||
.phylink_get_caps = sja1105_phylink_get_caps,
|
||||
.phylink_mac_select_pcs = sja1105_mac_select_pcs,
|
||||
.phylink_mac_link_up = sja1105_mac_link_up,
|
||||
.phylink_mac_link_down = sja1105_mac_link_down,
|
||||
.get_strings = sja1105_get_strings,
|
||||
.get_ethtool_stats = sja1105_get_ethtool_stats,
|
||||
.get_sset_count = sja1105_get_sset_count,
|
||||
@@ -3375,6 +3390,7 @@ static int sja1105_probe(struct spi_device *spi)
|
||||
ds->dev = dev;
|
||||
ds->num_ports = priv->info->num_ports;
|
||||
ds->ops = &sja1105_switch_ops;
|
||||
ds->phylink_mac_ops = &sja1105_phylink_mac_ops;
|
||||
ds->priv = priv;
|
||||
priv->ds = ds;
|
||||
|
||||
|
||||
@@ -459,7 +459,7 @@ struct ice_q_vector {
|
||||
struct ice_vsi *vsi;
|
||||
|
||||
u16 v_idx; /* index in the vsi->q_vector array. */
|
||||
u16 reg_idx;
|
||||
u16 reg_idx; /* PF relative register index */
|
||||
u8 num_ring_rx; /* total number of Rx rings in vector */
|
||||
u8 num_ring_tx; /* total number of Tx rings in vector */
|
||||
u8 wb_on_itr:1; /* if true, WB on ITR is enabled */
|
||||
@@ -481,6 +481,7 @@ struct ice_q_vector {
|
||||
char name[ICE_INT_NAME_STR_LEN];
|
||||
|
||||
u16 total_events; /* net_dim(): number of interrupts processed */
|
||||
u16 vf_reg_idx; /* VF relative register index */
|
||||
struct msi_map irq;
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
|
||||
q_vector->irq.index = -ENOENT;
|
||||
|
||||
if (vsi->type == ICE_VSI_VF) {
|
||||
q_vector->reg_idx = ice_calc_vf_reg_idx(vsi->vf, q_vector);
|
||||
ice_calc_vf_reg_idx(vsi->vf, q_vector);
|
||||
goto out;
|
||||
} else if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
|
||||
struct ice_vsi *ctrl_vsi = ice_get_vf_ctrl_vsi(pf, vsi);
|
||||
@@ -145,6 +145,7 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
|
||||
|
||||
skip_alloc:
|
||||
q_vector->reg_idx = q_vector->irq.index;
|
||||
q_vector->vf_reg_idx = q_vector->irq.index;
|
||||
|
||||
/* only set affinity_mask if the CPU is online */
|
||||
if (cpu_online(v_idx))
|
||||
|
||||
@@ -41,6 +41,8 @@ static struct in6_addr zero_ipv6_addr_mask = {
|
||||
static int ice_fltr_to_ethtool_flow(enum ice_fltr_ptype flow)
|
||||
{
|
||||
switch (flow) {
|
||||
case ICE_FLTR_PTYPE_NONF_ETH:
|
||||
return ETHER_FLOW;
|
||||
case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
|
||||
return TCP_V4_FLOW;
|
||||
case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
|
||||
@@ -72,6 +74,8 @@ static int ice_fltr_to_ethtool_flow(enum ice_fltr_ptype flow)
|
||||
static enum ice_fltr_ptype ice_ethtool_flow_to_fltr(int eth)
|
||||
{
|
||||
switch (eth) {
|
||||
case ETHER_FLOW:
|
||||
return ICE_FLTR_PTYPE_NONF_ETH;
|
||||
case TCP_V4_FLOW:
|
||||
return ICE_FLTR_PTYPE_NONF_IPV4_TCP;
|
||||
case UDP_V4_FLOW:
|
||||
@@ -137,6 +141,10 @@ int ice_get_ethtool_fdir_entry(struct ice_hw *hw, struct ethtool_rxnfc *cmd)
|
||||
memset(&fsp->m_ext, 0, sizeof(fsp->m_ext));
|
||||
|
||||
switch (fsp->flow_type) {
|
||||
case ETHER_FLOW:
|
||||
fsp->h_u.ether_spec = rule->eth;
|
||||
fsp->m_u.ether_spec = rule->eth_mask;
|
||||
break;
|
||||
case IPV4_USER_FLOW:
|
||||
fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
|
||||
fsp->h_u.usr_ip4_spec.proto = 0;
|
||||
@@ -1193,6 +1201,122 @@ ice_set_fdir_ip6_usr_seg(struct ice_flow_seg_info *seg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_fdir_vlan_valid - validate VLAN data for Flow Director rule
|
||||
* @dev: network interface device structure
|
||||
* @fsp: pointer to ethtool Rx flow specification
|
||||
*
|
||||
* Return: true if vlan data is valid, false otherwise
|
||||
*/
|
||||
static bool ice_fdir_vlan_valid(struct device *dev,
|
||||
struct ethtool_rx_flow_spec *fsp)
|
||||
{
|
||||
if (fsp->m_ext.vlan_etype && !eth_type_vlan(fsp->h_ext.vlan_etype))
|
||||
return false;
|
||||
|
||||
if (fsp->m_ext.vlan_tci && ntohs(fsp->h_ext.vlan_tci) >= VLAN_N_VID)
|
||||
return false;
|
||||
|
||||
/* proto and vlan must have vlan-etype defined */
|
||||
if (fsp->m_u.ether_spec.h_proto && fsp->m_ext.vlan_tci &&
|
||||
!fsp->m_ext.vlan_etype) {
|
||||
dev_warn(dev, "Filter with proto and vlan require also vlan-etype");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_ether_flow_seg - set address and protocol segments for ether flow
|
||||
* @dev: network interface device structure
|
||||
* @seg: flow segment for programming
|
||||
* @eth_spec: mask data from ethtool
|
||||
*
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
static int ice_set_ether_flow_seg(struct device *dev,
|
||||
struct ice_flow_seg_info *seg,
|
||||
struct ethhdr *eth_spec)
|
||||
{
|
||||
ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ETH);
|
||||
|
||||
/* empty rules are not valid */
|
||||
if (is_zero_ether_addr(eth_spec->h_source) &&
|
||||
is_zero_ether_addr(eth_spec->h_dest) &&
|
||||
!eth_spec->h_proto)
|
||||
return -EINVAL;
|
||||
|
||||
/* Ethertype */
|
||||
if (eth_spec->h_proto == htons(0xFFFF)) {
|
||||
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_TYPE,
|
||||
ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL, false);
|
||||
} else if (eth_spec->h_proto) {
|
||||
dev_warn(dev, "Only 0x0000 or 0xffff proto mask is allowed for flow-type ether");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Source MAC address */
|
||||
if (is_broadcast_ether_addr(eth_spec->h_source))
|
||||
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_SA,
|
||||
ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL, false);
|
||||
else if (!is_zero_ether_addr(eth_spec->h_source))
|
||||
goto err_mask;
|
||||
|
||||
/* Destination MAC address */
|
||||
if (is_broadcast_ether_addr(eth_spec->h_dest))
|
||||
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_DA,
|
||||
ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL, false);
|
||||
else if (!is_zero_ether_addr(eth_spec->h_dest))
|
||||
goto err_mask;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mask:
|
||||
dev_warn(dev, "Only 00:00:00:00:00:00 or ff:ff:ff:ff:ff:ff MAC address mask is allowed for flow-type ether");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_fdir_vlan_seg - set vlan segments for ether flow
|
||||
* @seg: flow segment for programming
|
||||
* @ext_masks: masks for additional RX flow fields
|
||||
*
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
static int
|
||||
ice_set_fdir_vlan_seg(struct ice_flow_seg_info *seg,
|
||||
struct ethtool_flow_ext *ext_masks)
|
||||
{
|
||||
ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_VLAN);
|
||||
|
||||
if (ext_masks->vlan_etype) {
|
||||
if (ext_masks->vlan_etype != htons(0xFFFF))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_S_VLAN,
|
||||
ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL, false);
|
||||
}
|
||||
|
||||
if (ext_masks->vlan_tci) {
|
||||
if (ext_masks->vlan_tci != htons(0xFFFF))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_C_VLAN,
|
||||
ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL,
|
||||
ICE_FLOW_FLD_OFF_INVAL, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_cfg_fdir_xtrct_seq - Configure extraction sequence for the given filter
|
||||
* @pf: PF structure
|
||||
@@ -1209,7 +1333,7 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
|
||||
struct device *dev = ice_pf_to_dev(pf);
|
||||
enum ice_fltr_ptype fltr_idx;
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
bool perfect_filter;
|
||||
bool perfect_filter = false;
|
||||
int ret;
|
||||
|
||||
seg = devm_kzalloc(dev, sizeof(*seg), GFP_KERNEL);
|
||||
@@ -1262,6 +1386,16 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
|
||||
ret = ice_set_fdir_ip6_usr_seg(seg, &fsp->m_u.usr_ip6_spec,
|
||||
&perfect_filter);
|
||||
break;
|
||||
case ETHER_FLOW:
|
||||
ret = ice_set_ether_flow_seg(dev, seg, &fsp->m_u.ether_spec);
|
||||
if (!ret && (fsp->m_ext.vlan_etype || fsp->m_ext.vlan_tci)) {
|
||||
if (!ice_fdir_vlan_valid(dev, fsp)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = ice_set_fdir_vlan_seg(seg, &fsp->m_ext);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
@@ -1823,6 +1957,10 @@ ice_set_fdir_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,
|
||||
input->mask.v6.tc = fsp->m_u.usr_ip6_spec.tclass;
|
||||
input->mask.v6.proto = fsp->m_u.usr_ip6_spec.l4_proto;
|
||||
break;
|
||||
case ETHER_FLOW:
|
||||
input->eth = fsp->h_u.ether_spec;
|
||||
input->eth_mask = fsp->m_u.ether_spec;
|
||||
break;
|
||||
default:
|
||||
/* not doing un-parsed flow types */
|
||||
return -EINVAL;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "ice_common.h"
|
||||
|
||||
/* These are training packet headers used to program flow director filters. */
|
||||
static const u8 ice_fdir_eth_pkt[22];
|
||||
|
||||
static const u8 ice_fdir_tcpv4_pkt[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
|
||||
@@ -416,6 +418,11 @@ static const u8 ice_fdir_ip6_tun_pkt[] = {
|
||||
|
||||
/* Flow Director no-op training packet table */
|
||||
static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
|
||||
{
|
||||
ICE_FLTR_PTYPE_NONF_ETH,
|
||||
sizeof(ice_fdir_eth_pkt), ice_fdir_eth_pkt,
|
||||
sizeof(ice_fdir_eth_pkt), ice_fdir_eth_pkt,
|
||||
},
|
||||
{
|
||||
ICE_FLTR_PTYPE_NONF_IPV4_TCP,
|
||||
sizeof(ice_fdir_tcpv4_pkt), ice_fdir_tcpv4_pkt,
|
||||
@@ -914,6 +921,21 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
|
||||
* perspective. The input from user is from Rx filter perspective.
|
||||
*/
|
||||
switch (flow) {
|
||||
case ICE_FLTR_PTYPE_NONF_ETH:
|
||||
ice_pkt_insert_mac_addr(loc, input->eth.h_dest);
|
||||
ice_pkt_insert_mac_addr(loc + ETH_ALEN, input->eth.h_source);
|
||||
if (input->ext_data.vlan_tag || input->ext_data.vlan_type) {
|
||||
ice_pkt_insert_u16(loc, ICE_ETH_TYPE_F_OFFSET,
|
||||
input->ext_data.vlan_type);
|
||||
ice_pkt_insert_u16(loc, ICE_ETH_VLAN_TCI_OFFSET,
|
||||
input->ext_data.vlan_tag);
|
||||
ice_pkt_insert_u16(loc, ICE_ETH_TYPE_VLAN_OFFSET,
|
||||
input->eth.h_proto);
|
||||
} else {
|
||||
ice_pkt_insert_u16(loc, ICE_ETH_TYPE_F_OFFSET,
|
||||
input->eth.h_proto);
|
||||
}
|
||||
break;
|
||||
case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
|
||||
ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
|
||||
input->ip.v4.src_ip);
|
||||
@@ -1189,52 +1211,58 @@ static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
|
||||
* ice_fdir_comp_rules - compare 2 filters
|
||||
* @a: a Flow Director filter data structure
|
||||
* @b: a Flow Director filter data structure
|
||||
* @v6: bool true if v6 filter
|
||||
*
|
||||
* Returns true if the filters match
|
||||
*/
|
||||
static bool
|
||||
ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b, bool v6)
|
||||
ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b)
|
||||
{
|
||||
enum ice_fltr_ptype flow_type = a->flow_type;
|
||||
|
||||
/* The calling function already checks that the two filters have the
|
||||
* same flow_type.
|
||||
*/
|
||||
if (!v6) {
|
||||
if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
|
||||
flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
|
||||
flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
|
||||
if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
|
||||
a->ip.v4.src_ip == b->ip.v4.src_ip &&
|
||||
a->ip.v4.dst_port == b->ip.v4.dst_port &&
|
||||
a->ip.v4.src_port == b->ip.v4.src_port)
|
||||
return true;
|
||||
} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
|
||||
if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
|
||||
a->ip.v4.src_ip == b->ip.v4.src_ip &&
|
||||
a->ip.v4.l4_header == b->ip.v4.l4_header &&
|
||||
a->ip.v4.proto == b->ip.v4.proto &&
|
||||
a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
|
||||
a->ip.v4.tos == b->ip.v4.tos)
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
|
||||
flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
|
||||
flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
|
||||
if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
|
||||
a->ip.v6.src_port == b->ip.v6.src_port &&
|
||||
!ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
|
||||
b->ip.v6.dst_ip) &&
|
||||
!ice_cmp_ipv6_addr(a->ip.v6.src_ip,
|
||||
b->ip.v6.src_ip))
|
||||
return true;
|
||||
} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
|
||||
if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
|
||||
a->ip.v6.src_port == b->ip.v6.src_port)
|
||||
return true;
|
||||
}
|
||||
switch (flow_type) {
|
||||
case ICE_FLTR_PTYPE_NONF_ETH:
|
||||
if (!memcmp(&a->eth, &b->eth, sizeof(a->eth)))
|
||||
return true;
|
||||
break;
|
||||
case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
|
||||
case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
|
||||
case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
|
||||
if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
|
||||
a->ip.v4.src_ip == b->ip.v4.src_ip &&
|
||||
a->ip.v4.dst_port == b->ip.v4.dst_port &&
|
||||
a->ip.v4.src_port == b->ip.v4.src_port)
|
||||
return true;
|
||||
break;
|
||||
case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
|
||||
if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
|
||||
a->ip.v4.src_ip == b->ip.v4.src_ip &&
|
||||
a->ip.v4.l4_header == b->ip.v4.l4_header &&
|
||||
a->ip.v4.proto == b->ip.v4.proto &&
|
||||
a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
|
||||
a->ip.v4.tos == b->ip.v4.tos)
|
||||
return true;
|
||||
break;
|
||||
case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
|
||||
case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
|
||||
case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
|
||||
if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
|
||||
a->ip.v6.src_port == b->ip.v6.src_port &&
|
||||
!ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
|
||||
b->ip.v6.dst_ip) &&
|
||||
!ice_cmp_ipv6_addr(a->ip.v6.src_ip,
|
||||
b->ip.v6.src_ip))
|
||||
return true;
|
||||
break;
|
||||
case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
|
||||
if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
|
||||
a->ip.v6.src_port == b->ip.v6.src_port)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1253,19 +1281,10 @@ bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
|
||||
bool ret = false;
|
||||
|
||||
list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
|
||||
enum ice_fltr_ptype flow_type;
|
||||
|
||||
if (rule->flow_type != input->flow_type)
|
||||
continue;
|
||||
|
||||
flow_type = input->flow_type;
|
||||
if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
|
||||
flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
|
||||
flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
|
||||
flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
|
||||
ret = ice_fdir_comp_rules(rule, input, false);
|
||||
else
|
||||
ret = ice_fdir_comp_rules(rule, input, true);
|
||||
ret = ice_fdir_comp_rules(rule, input);
|
||||
if (ret) {
|
||||
if (rule->fltr_id == input->fltr_id &&
|
||||
rule->q_index != input->q_index)
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#define ICE_FDIR_MAX_RAW_PKT_SIZE (512 + ICE_FDIR_TUN_PKT_OFF)
|
||||
|
||||
/* macros for offsets into packets for flow director programming */
|
||||
#define ICE_ETH_TYPE_F_OFFSET 12
|
||||
#define ICE_ETH_VLAN_TCI_OFFSET 14
|
||||
#define ICE_ETH_TYPE_VLAN_OFFSET 16
|
||||
#define ICE_IPV4_SRC_ADDR_OFFSET 26
|
||||
#define ICE_IPV4_DST_ADDR_OFFSET 30
|
||||
#define ICE_IPV4_TCP_SRC_PORT_OFFSET 34
|
||||
@@ -159,6 +162,8 @@ struct ice_fdir_fltr {
|
||||
struct list_head fltr_node;
|
||||
enum ice_fltr_ptype flow_type;
|
||||
|
||||
struct ethhdr eth, eth_mask;
|
||||
|
||||
union {
|
||||
struct ice_fdir_v4 v4;
|
||||
struct ice_fdir_v6 v6;
|
||||
|
||||
@@ -360,13 +360,14 @@ static void ice_ena_vf_mappings(struct ice_vf *vf)
|
||||
* @vf: VF to calculate the register index for
|
||||
* @q_vector: a q_vector associated to the VF
|
||||
*/
|
||||
int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector)
|
||||
void ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector)
|
||||
{
|
||||
if (!vf || !q_vector)
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
/* always add one to account for the OICR being the first MSIX */
|
||||
return vf->first_vector_idx + q_vector->v_idx + 1;
|
||||
q_vector->vf_reg_idx = q_vector->v_idx + ICE_NONQ_VECS_VF;
|
||||
q_vector->reg_idx = vf->first_vector_idx + q_vector->vf_reg_idx;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -831,11 +832,6 @@ static int ice_create_vf_entries(struct ice_pf *pf, u16 num_vfs)
|
||||
|
||||
pci_dev_get(vfdev);
|
||||
|
||||
/* set default number of MSI-X */
|
||||
vf->num_msix = pf->vfs.num_msix_per;
|
||||
vf->num_vf_qs = pf->vfs.num_qps_per;
|
||||
ice_vc_set_default_allowlist(vf);
|
||||
|
||||
hash_add_rcu(vfs->table, &vf->entry, vf_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state);
|
||||
|
||||
int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena);
|
||||
|
||||
int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector);
|
||||
void ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector);
|
||||
|
||||
int
|
||||
ice_get_vf_stats(struct net_device *netdev, int vf_id,
|
||||
@@ -130,11 +130,10 @@ ice_set_vf_bw(struct net_device __always_unused *netdev,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline void
|
||||
ice_calc_vf_reg_idx(struct ice_vf __always_unused *vf,
|
||||
struct ice_q_vector __always_unused *q_vector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
||||
@@ -203,6 +203,7 @@ struct ice_phy_info {
|
||||
enum ice_fltr_ptype {
|
||||
/* NONE - used for undef/error */
|
||||
ICE_FLTR_PTYPE_NONF_NONE = 0,
|
||||
ICE_FLTR_PTYPE_NONF_ETH,
|
||||
ICE_FLTR_PTYPE_NONF_IPV4_UDP,
|
||||
ICE_FLTR_PTYPE_NONF_IPV4_TCP,
|
||||
ICE_FLTR_PTYPE_NONF_IPV4_SCTP,
|
||||
|
||||
@@ -992,10 +992,13 @@ void ice_initialize_vf_entry(struct ice_vf *vf)
|
||||
|
||||
/* assign default capabilities */
|
||||
vf->spoofchk = true;
|
||||
vf->num_vf_qs = vfs->num_qps_per;
|
||||
ice_vc_set_default_allowlist(vf);
|
||||
ice_virtchnl_set_dflt_ops(vf);
|
||||
|
||||
/* set default number of MSI-X */
|
||||
vf->num_msix = vfs->num_msix_per;
|
||||
vf->num_vf_qs = vfs->num_qps_per;
|
||||
|
||||
/* ctrl_vsi_idx will be set to a valid value only when iAVF
|
||||
* creates its first fdir rule.
|
||||
*/
|
||||
|
||||
@@ -1505,13 +1505,12 @@ error_param:
|
||||
* ice_cfg_interrupt
|
||||
* @vf: pointer to the VF info
|
||||
* @vsi: the VSI being configured
|
||||
* @vector_id: vector ID
|
||||
* @map: vector map for mapping vectors to queues
|
||||
* @q_vector: structure for interrupt vector
|
||||
* configure the IRQ to queue map
|
||||
*/
|
||||
static int
|
||||
ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id,
|
||||
static enum virtchnl_status_code
|
||||
ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi,
|
||||
struct virtchnl_vector_map *map,
|
||||
struct ice_q_vector *q_vector)
|
||||
{
|
||||
@@ -1531,7 +1530,8 @@ ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id,
|
||||
q_vector->num_ring_rx++;
|
||||
q_vector->rx.itr_idx = map->rxitr_idx;
|
||||
vsi->rx_rings[vsi_q_id]->q_vector = q_vector;
|
||||
ice_cfg_rxq_interrupt(vsi, vsi_q_id, vector_id,
|
||||
ice_cfg_rxq_interrupt(vsi, vsi_q_id,
|
||||
q_vector->vf_reg_idx,
|
||||
q_vector->rx.itr_idx);
|
||||
}
|
||||
|
||||
@@ -1545,7 +1545,8 @@ ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id,
|
||||
q_vector->num_ring_tx++;
|
||||
q_vector->tx.itr_idx = map->txitr_idx;
|
||||
vsi->tx_rings[vsi_q_id]->q_vector = q_vector;
|
||||
ice_cfg_txq_interrupt(vsi, vsi_q_id, vector_id,
|
||||
ice_cfg_txq_interrupt(vsi, vsi_q_id,
|
||||
q_vector->vf_reg_idx,
|
||||
q_vector->tx.itr_idx);
|
||||
}
|
||||
|
||||
@@ -1619,8 +1620,7 @@ static int ice_vc_cfg_irq_map_msg(struct ice_vf *vf, u8 *msg)
|
||||
}
|
||||
|
||||
/* lookout for the invalid queue index */
|
||||
v_ret = (enum virtchnl_status_code)
|
||||
ice_cfg_interrupt(vf, vsi, vector_id, map, q_vector);
|
||||
v_ret = ice_cfg_interrupt(vf, vsi, map, q_vector);
|
||||
if (v_ret)
|
||||
goto error_param;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/netdev_queues.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/rtnetlink.h>
|
||||
@@ -299,6 +300,29 @@ static int nsim_get_iflink(const struct net_device *dev)
|
||||
return iflink;
|
||||
}
|
||||
|
||||
static int nsim_open(struct net_device *dev)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
struct page_pool_params pp = { 0 };
|
||||
|
||||
pp.pool_size = 128;
|
||||
pp.dev = &dev->dev;
|
||||
pp.dma_dir = DMA_BIDIRECTIONAL;
|
||||
pp.netdev = dev;
|
||||
|
||||
ns->pp = page_pool_create(&pp);
|
||||
return PTR_ERR_OR_ZERO(ns->pp);
|
||||
}
|
||||
|
||||
static int nsim_stop(struct net_device *dev)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(dev);
|
||||
|
||||
page_pool_destroy(ns->pp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops nsim_netdev_ops = {
|
||||
.ndo_start_xmit = nsim_start_xmit,
|
||||
.ndo_set_rx_mode = nsim_set_rx_mode,
|
||||
@@ -318,6 +342,8 @@ static const struct net_device_ops nsim_netdev_ops = {
|
||||
.ndo_set_features = nsim_set_features,
|
||||
.ndo_get_iflink = nsim_get_iflink,
|
||||
.ndo_bpf = nsim_bpf,
|
||||
.ndo_open = nsim_open,
|
||||
.ndo_stop = nsim_stop,
|
||||
};
|
||||
|
||||
static const struct net_device_ops nsim_vf_netdev_ops = {
|
||||
@@ -378,6 +404,60 @@ static const struct netdev_stat_ops nsim_stat_ops = {
|
||||
.get_base_stats = nsim_get_base_stats,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
nsim_pp_hold_read(struct file *file, char __user *data,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct netdevsim *ns = file->private_data;
|
||||
char buf[3] = "n\n";
|
||||
|
||||
if (ns->page)
|
||||
buf[0] = 'y';
|
||||
|
||||
return simple_read_from_buffer(data, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
nsim_pp_hold_write(struct file *file, const char __user *data,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct netdevsim *ns = file->private_data;
|
||||
ssize_t ret;
|
||||
bool val;
|
||||
|
||||
ret = kstrtobool_from_user(data, count, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rtnl_lock();
|
||||
ret = count;
|
||||
if (val == !!ns->page)
|
||||
goto exit;
|
||||
|
||||
if (!netif_running(ns->netdev) && val) {
|
||||
ret = -ENETDOWN;
|
||||
} else if (val) {
|
||||
ns->page = page_pool_dev_alloc_pages(ns->pp);
|
||||
if (!ns->page)
|
||||
ret = -ENOMEM;
|
||||
} else {
|
||||
page_pool_put_full_page(ns->page->pp, ns->page, false);
|
||||
ns->page = NULL;
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
exit:
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations nsim_pp_hold_fops = {
|
||||
.open = simple_open,
|
||||
.read = nsim_pp_hold_read,
|
||||
.write = nsim_pp_hold_write,
|
||||
.llseek = generic_file_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void nsim_setup(struct net_device *dev)
|
||||
{
|
||||
ether_setup(dev);
|
||||
@@ -485,6 +565,10 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
|
||||
err = nsim_init_netdevsim_vf(ns);
|
||||
if (err)
|
||||
goto err_free_netdev;
|
||||
|
||||
ns->pp_dfs = debugfs_create_file("pp_hold", 0600, nsim_dev_port->ddir,
|
||||
ns, &nsim_pp_hold_fops);
|
||||
|
||||
return ns;
|
||||
|
||||
err_free_netdev:
|
||||
@@ -497,6 +581,8 @@ void nsim_destroy(struct netdevsim *ns)
|
||||
struct net_device *dev = ns->netdev;
|
||||
struct netdevsim *peer;
|
||||
|
||||
debugfs_remove(ns->pp_dfs);
|
||||
|
||||
rtnl_lock();
|
||||
peer = rtnl_dereference(ns->peer);
|
||||
if (peer)
|
||||
@@ -511,6 +597,13 @@ void nsim_destroy(struct netdevsim *ns)
|
||||
rtnl_unlock();
|
||||
if (nsim_dev_port_is_pf(ns->nsim_dev_port))
|
||||
nsim_exit_netdevsim(ns);
|
||||
|
||||
/* Put this intentionally late to exercise the orphaning path */
|
||||
if (ns->page) {
|
||||
page_pool_put_full_page(ns->page->pp, ns->page, false);
|
||||
ns->page = NULL;
|
||||
}
|
||||
|
||||
free_netdev(dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,10 @@ struct netdevsim {
|
||||
struct debugfs_u32_array dfs_ports[2];
|
||||
} udp_ports;
|
||||
|
||||
struct page_pool *pp;
|
||||
struct page *page;
|
||||
struct dentry *pp_dfs;
|
||||
|
||||
struct nsim_ethtool ethtool;
|
||||
struct netdevsim __rcu *peer;
|
||||
};
|
||||
|
||||
@@ -996,9 +996,11 @@ class YnlFamily(SpecFamily):
|
||||
rsp_msg.update(self._decode_struct(decoded.raw, op.fixed_header))
|
||||
rsp.append(rsp_msg)
|
||||
|
||||
if dump:
|
||||
return rsp
|
||||
if not rsp:
|
||||
return None
|
||||
if not dump and len(rsp) == 1:
|
||||
if len(rsp) == 1:
|
||||
return rsp[0]
|
||||
return rsp
|
||||
|
||||
|
||||
@@ -65,9 +65,8 @@ same_speeds_autoneg_off()
|
||||
setup_wait_dev_with_timeout $h1
|
||||
setup_wait_dev_with_timeout $h2
|
||||
ping_do $h1 192.0.2.2
|
||||
check_err $? "speed $speed autoneg off"
|
||||
log_test "force of same speed autoneg off"
|
||||
log_info "speed = $speed"
|
||||
check_err $? "ping with speed $speed autoneg off"
|
||||
log_test "force speed $speed on both ends"
|
||||
done
|
||||
|
||||
ethtool -s $h2 autoneg on
|
||||
@@ -112,9 +111,8 @@ combination_of_neg_on_and_off()
|
||||
setup_wait_dev_with_timeout $h1
|
||||
setup_wait_dev_with_timeout $h2
|
||||
ping_do $h1 192.0.2.2
|
||||
check_err $? "h1-speed=$speed autoneg off, h2 autoneg on"
|
||||
log_test "one side with autoneg off and another with autoneg on"
|
||||
log_info "force speed = $speed"
|
||||
check_err $? "ping with h1-speed=$speed autoneg off, h2 autoneg on"
|
||||
log_test "force speed $speed vs. autoneg"
|
||||
done
|
||||
|
||||
ethtool -s $h1 autoneg on
|
||||
@@ -207,10 +205,9 @@ advertise_subset_of_speeds()
|
||||
setup_wait_dev_with_timeout $h1
|
||||
setup_wait_dev_with_timeout $h2
|
||||
ping_do $h1 192.0.2.2
|
||||
check_err $? "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise ($speed_value)"
|
||||
check_err $? "ping with h1=$speed_1_to_advertise, h2=$speed_2_to_advertise ($speed_value)"
|
||||
|
||||
log_test "advertise subset of speeds"
|
||||
log_info "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise"
|
||||
log_test "advertise $speed_1_to_advertise vs. $speed_2_to_advertise"
|
||||
done
|
||||
|
||||
ethtool -s $h2 autoneg on
|
||||
|
||||
@@ -44,6 +44,7 @@ bucket_test()
|
||||
# Mausezahn does not include FCS bytes in its length - but the
|
||||
# histogram counters do
|
||||
len=$((len - ETH_FCS_LEN))
|
||||
len=$((len > 0 ? len : 0))
|
||||
|
||||
before=$(ethtool --json -S $iface --groups rmon | \
|
||||
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
|
||||
|
||||
@@ -50,6 +50,7 @@ ALL_TESTS="
|
||||
NUM_NETIFS=4
|
||||
lib_dir=$(dirname "$0")
|
||||
source "$lib_dir"/../../../net/forwarding/lib.sh
|
||||
source "$lib_dir"/../../../net/forwarding/tc_common.sh
|
||||
|
||||
h1_create()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ NUM_NETIFS=6
|
||||
lib_dir=$(dirname "$0")
|
||||
source "$lib_dir"/../../../net/forwarding/lib.sh
|
||||
source "$lib_dir"/../../../net/forwarding/ipip_lib.sh
|
||||
source "$lib_dir"/../../../net/forwarding/tc_common.sh
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
|
||||
@@ -24,8 +24,8 @@ setup_prepare()
|
||||
busywait "$TIMEOUT" wait_for_port_up ethtool $swp2
|
||||
check_err $? "ports did not come up"
|
||||
|
||||
local lanes_exist=$(ethtool $swp1 | grep 'Lanes:')
|
||||
if [[ -z $lanes_exist ]]; then
|
||||
busywait $TIMEOUT sh -c "ethtool $swp1 | grep -q Lanes:"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
log_test "SKIP: driver does not support lanes setting"
|
||||
exit 1
|
||||
fi
|
||||
@@ -122,8 +122,9 @@ autoneg()
|
||||
ethtool_set $swp1 speed $max_speed lanes $lanes
|
||||
ip link set dev $swp1 up
|
||||
ip link set dev $swp2 up
|
||||
busywait "$TIMEOUT" wait_for_port_up ethtool $swp2
|
||||
check_err $? "ports did not come up"
|
||||
|
||||
busywait $TIMEOUT sh -c "ethtool $swp1 | grep -q Lanes:"
|
||||
check_err $? "Lanes parameter is not presented on time"
|
||||
|
||||
check_lanes $swp1 $lanes $max_speed
|
||||
log_test "$lanes lanes is autonegotiated"
|
||||
@@ -160,8 +161,9 @@ autoneg_force_mode()
|
||||
ethtool_set $swp2 speed $max_speed lanes $lanes autoneg off
|
||||
ip link set dev $swp1 up
|
||||
ip link set dev $swp2 up
|
||||
busywait "$TIMEOUT" wait_for_port_up ethtool $swp2
|
||||
check_err $? "ports did not come up"
|
||||
|
||||
busywait $TIMEOUT sh -c "ethtool $swp1 | grep -q Lanes:"
|
||||
check_err $? "Lanes parameter is not presented on time"
|
||||
|
||||
check_lanes $swp1 $lanes $max_speed
|
||||
log_test "Autoneg off, $lanes lanes detected during force mode"
|
||||
|
||||
@@ -95,27 +95,9 @@ source "$net_forwarding_dir/../lib.sh"
|
||||
# timeout in seconds
|
||||
slowwait()
|
||||
{
|
||||
local timeout=$1; shift
|
||||
local timeout_sec=$1; shift
|
||||
|
||||
local start_time="$(date -u +%s)"
|
||||
while true
|
||||
do
|
||||
local out
|
||||
out=$("$@")
|
||||
local ret=$?
|
||||
if ((!ret)); then
|
||||
echo -n "$out"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local current_time="$(date -u +%s)"
|
||||
if ((current_time - start_time > timeout)); then
|
||||
echo -n "$out"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 0.1
|
||||
done
|
||||
loopy_wait "sleep 0.1" "$((timeout_sec * 1000))" "$@"
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
@@ -291,11 +273,6 @@ if [[ "$REQUIRE_MTOOLS" = "yes" ]]; then
|
||||
require_command mreceive
|
||||
fi
|
||||
|
||||
if [[ ! -v NUM_NETIFS ]]; then
|
||||
echo "SKIP: importer does not define \"NUM_NETIFS\""
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
##############################################################################
|
||||
# Command line options handling
|
||||
|
||||
@@ -314,6 +291,23 @@ done
|
||||
##############################################################################
|
||||
# Network interfaces configuration
|
||||
|
||||
if [[ ! -v NUM_NETIFS ]]; then
|
||||
echo "SKIP: importer does not define \"NUM_NETIFS\""
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
if (( NUM_NETIFS > ${#NETIFS[@]} )); then
|
||||
echo "SKIP: Importer requires $NUM_NETIFS NETIFS, but only ${#NETIFS[@]} are defined (${NETIFS[@]})"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
for i in $(seq ${#NETIFS[@]}); do
|
||||
if [[ ! ${NETIFS[p$i]} ]]; then
|
||||
echo "SKIP: NETIFS[p$i] not given"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
done
|
||||
|
||||
create_netif_veth()
|
||||
{
|
||||
local i
|
||||
@@ -2144,6 +2138,8 @@ bail_on_lldpad()
|
||||
{
|
||||
local reason1="$1"; shift
|
||||
local reason2="$1"; shift
|
||||
local caller=${FUNCNAME[1]}
|
||||
local src=${BASH_SOURCE[1]}
|
||||
|
||||
if systemctl is-active --quiet lldpad; then
|
||||
|
||||
@@ -2164,7 +2160,8 @@ bail_on_lldpad()
|
||||
an environment variable ALLOW_LLDPAD to a
|
||||
non-empty string.
|
||||
EOF
|
||||
exit 1
|
||||
log_test_skip $src:$caller
|
||||
exit $EXIT_STATUS
|
||||
else
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,41 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# +-------------------------+
|
||||
# | H1 |
|
||||
# | $h1 + |
|
||||
# | 192.0.2.2/24 | |
|
||||
# | 2001:db8:1::2/64 | |
|
||||
# +-------------------|-----+
|
||||
# |
|
||||
# +-------------------|----------------------+
|
||||
# | | R1 |
|
||||
# | $rp11 + |
|
||||
# | 192.0.2.1/24 |
|
||||
# | 2001:db8:1::1/64 |
|
||||
# | |
|
||||
# | + $rp12 + $rp13 |
|
||||
# | | 169.254.2.12/24 | 169.254.3.13/24 |
|
||||
# | | fe80:2::12/64 | fe80:3::13/64 |
|
||||
# +--|--------------------|------------------+
|
||||
# | |
|
||||
# +--|--------------------|------------------+
|
||||
# | + $rp22 + $rp23 |
|
||||
# | 169.254.2.22/24 169.254.3.23/24 |
|
||||
# | fe80:2::22/64 fe80:3::23/64 |
|
||||
# | |
|
||||
# | $rp21 + |
|
||||
# | 198.51.100.1/24 | |
|
||||
# | 2001:db8:2::1/64 | R2 |
|
||||
# +-------------------|----------------------+
|
||||
# |
|
||||
# +-------------------|-----+
|
||||
# | | |
|
||||
# | $h2 + |
|
||||
# | 198.51.100.2/24 |
|
||||
# | 2001:db8:2::2/64 H2 |
|
||||
# +-------------------------+
|
||||
|
||||
ALL_TESTS="
|
||||
ping_ipv4
|
||||
ping_ipv6
|
||||
|
||||
@@ -1,6 +1,41 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# +-------------------------+
|
||||
# | H1 |
|
||||
# | $h1 + |
|
||||
# | 192.0.2.2/24 | |
|
||||
# | 2001:db8:1::2/64 | |
|
||||
# +-------------------|-----+
|
||||
# |
|
||||
# +-------------------|----------------------+
|
||||
# | | R1 |
|
||||
# | $rp11 + |
|
||||
# | 192.0.2.1/24 |
|
||||
# | 2001:db8:1::1/64 |
|
||||
# | |
|
||||
# | + $rp12 + $rp13 |
|
||||
# | | 169.254.2.12/24 | 169.254.3.13/24 |
|
||||
# | | fe80:2::12/64 | fe80:3::13/64 |
|
||||
# +--|--------------------|------------------+
|
||||
# | |
|
||||
# +--|--------------------|------------------+
|
||||
# | + $rp22 + $rp23 |
|
||||
# | 169.254.2.22/24 169.254.3.23/24 |
|
||||
# | fe80:2::22/64 fe80:3::23/64 |
|
||||
# | |
|
||||
# | $rp21 + |
|
||||
# | 198.51.100.1/24 | |
|
||||
# | 2001:db8:2::1/64 | R2 |
|
||||
# +-------------------|----------------------+
|
||||
# |
|
||||
# +-------------------|-----+
|
||||
# | | |
|
||||
# | $h2 + |
|
||||
# | 198.51.100.2/24 |
|
||||
# | 2001:db8:2::2/64 H2 |
|
||||
# +-------------------------+
|
||||
|
||||
ALL_TESTS="
|
||||
ping_ipv4
|
||||
ping_ipv6
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# +-------------------------+ +-------------------------+
|
||||
# | H1 | | H2 |
|
||||
# | $h1 + | | $h2 + |
|
||||
# | 192.0.2.2/24 | | | 198.51.100.2/24 | |
|
||||
# | 2001:db8:1::2/64 | | | 2001:db8:2::2/64 | |
|
||||
# +-------------------|-----+ +-------------------|-----+
|
||||
# | |
|
||||
# +-------------------|----------------------------|-----+
|
||||
# | R1 | | |
|
||||
# | $rp1 + $rp2 + |
|
||||
# | 192.0.2.1/24 198.51.100.1/24 |
|
||||
# | 2001:db8:1::1/64 2001:db8:2::1/64 |
|
||||
# +------------------------------------------------------+
|
||||
|
||||
ALL_TESTS="
|
||||
ping_ipv4
|
||||
ping_ipv6
|
||||
|
||||
@@ -58,9 +58,10 @@ ksft_exit_status_merge()
|
||||
$ksft_xfail $ksft_pass $ksft_skip $ksft_fail
|
||||
}
|
||||
|
||||
busywait()
|
||||
loopy_wait()
|
||||
{
|
||||
local timeout=$1; shift
|
||||
local sleep_cmd=$1; shift
|
||||
local timeout_ms=$1; shift
|
||||
|
||||
local start_time="$(date -u +%s%3N)"
|
||||
while true
|
||||
@@ -74,13 +75,22 @@ busywait()
|
||||
fi
|
||||
|
||||
local current_time="$(date -u +%s%3N)"
|
||||
if ((current_time - start_time > timeout)); then
|
||||
if ((current_time - start_time > timeout_ms)); then
|
||||
echo -n "$out"
|
||||
return 1
|
||||
fi
|
||||
|
||||
$sleep_cmd
|
||||
done
|
||||
}
|
||||
|
||||
busywait()
|
||||
{
|
||||
local timeout_ms=$1; shift
|
||||
|
||||
loopy_wait : "$timeout_ms" "$@"
|
||||
}
|
||||
|
||||
cleanup_ns()
|
||||
{
|
||||
local ns=""
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
import builtins
|
||||
import inspect
|
||||
import time
|
||||
import traceback
|
||||
from .consts import KSFT_MAIN_NAME
|
||||
|
||||
KSFT_RESULT = None
|
||||
@@ -18,32 +21,45 @@ def ksft_pr(*objs, **kwargs):
|
||||
print("#", *objs, **kwargs)
|
||||
|
||||
|
||||
def _fail(*args):
|
||||
global KSFT_RESULT
|
||||
KSFT_RESULT = False
|
||||
|
||||
frame = inspect.stack()[2]
|
||||
ksft_pr("At " + frame.filename + " line " + str(frame.lineno) + ":")
|
||||
ksft_pr(*args)
|
||||
|
||||
|
||||
def ksft_eq(a, b, comment=""):
|
||||
global KSFT_RESULT
|
||||
if a != b:
|
||||
KSFT_RESULT = False
|
||||
ksft_pr("Check failed", a, "!=", b, comment)
|
||||
_fail("Check failed", a, "!=", b, comment)
|
||||
|
||||
|
||||
def ksft_true(a, comment=""):
|
||||
global KSFT_RESULT
|
||||
if not a:
|
||||
KSFT_RESULT = False
|
||||
ksft_pr("Check failed", a, "does not eval to True", comment)
|
||||
_fail("Check failed", a, "does not eval to True", comment)
|
||||
|
||||
|
||||
def ksft_in(a, b, comment=""):
|
||||
global KSFT_RESULT
|
||||
if a not in b:
|
||||
KSFT_RESULT = False
|
||||
ksft_pr("Check failed", a, "not in", b, comment)
|
||||
_fail("Check failed", a, "not in", b, comment)
|
||||
|
||||
|
||||
def ksft_ge(a, b, comment=""):
|
||||
global KSFT_RESULT
|
||||
if a < b:
|
||||
KSFT_RESULT = False
|
||||
ksft_pr("Check failed", a, "<", b, comment)
|
||||
_fail("Check failed", a, "<", b, comment)
|
||||
|
||||
|
||||
def ksft_busy_wait(cond, sleep=0.005, deadline=1, comment=""):
|
||||
end = time.monotonic() + deadline
|
||||
while True:
|
||||
if cond():
|
||||
return
|
||||
if time.monotonic() > end:
|
||||
_fail("Waiting for condition timed out", comment)
|
||||
return
|
||||
time.sleep(sleep)
|
||||
|
||||
|
||||
def ktap_result(ok, cnt=1, case="", comment=""):
|
||||
@@ -82,7 +98,8 @@ def ksft_run(cases, args=()):
|
||||
totals['xfail'] += 1
|
||||
continue
|
||||
except Exception as e:
|
||||
for line in str(e).split('\n'):
|
||||
tb = traceback.format_exc()
|
||||
for line in tb.strip().split('\n'):
|
||||
ksft_pr("Exception|", line)
|
||||
ktap_result(False, cnt, case)
|
||||
totals['fail'] += 1
|
||||
|
||||
@@ -28,6 +28,7 @@ class NetdevSim:
|
||||
self.dfs_dir = "%s/ports/%u/" % (nsimdev.dfs_dir, port_index)
|
||||
ret = ip("-j link show dev %s" % ifname, ns=ns)
|
||||
self.dev = json.loads(ret.stdout)[0]
|
||||
self.ifindex = self.dev["ifindex"]
|
||||
|
||||
def dfs_write(self, path, val):
|
||||
self.nsimdev.dfs_write(f'ports/{self.port_index}/' + path, val)
|
||||
@@ -84,6 +85,17 @@ class NetdevSimDev:
|
||||
for port_index in range(port_count):
|
||||
self.nsims.append(self._make_port(port_index, ifnames[port_index]))
|
||||
|
||||
self.removed = False
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, ex_type, ex_value, ex_tb):
|
||||
"""
|
||||
__exit__ gets called at the end of a "with" block.
|
||||
"""
|
||||
self.remove()
|
||||
|
||||
def _make_port(self, port_index, ifname):
|
||||
return NetdevSim(self, port_index, ifname, self.ns)
|
||||
|
||||
@@ -112,7 +124,9 @@ class NetdevSimDev:
|
||||
raise Exception("netdevices did not appear within timeout")
|
||||
|
||||
def remove(self):
|
||||
self.ctrl_write("del_device", "%u" % (self.addr, ))
|
||||
if not self.removed:
|
||||
self.ctrl_write("del_device", "%u" % (self.addr, ))
|
||||
self.removed = True
|
||||
|
||||
def remove_nsim(self, nsim):
|
||||
self.nsims.remove(nsim)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
from lib.py import ksft_run, ksft_pr, ksft_eq, ksft_ge, NetdevFamily
|
||||
import time
|
||||
from lib.py import ksft_run, ksft_pr, ksft_eq, ksft_ge, ksft_busy_wait
|
||||
from lib.py import NetdevFamily, NetdevSimDev, ip
|
||||
|
||||
|
||||
def empty_check(nf) -> None:
|
||||
@@ -15,9 +17,79 @@ def lo_check(nf) -> None:
|
||||
ksft_eq(len(lo_info['xdp-rx-metadata-features']), 0)
|
||||
|
||||
|
||||
def page_pool_check(nf) -> None:
|
||||
with NetdevSimDev() as nsimdev:
|
||||
nsim = nsimdev.nsims[0]
|
||||
|
||||
def up():
|
||||
ip(f"link set dev {nsim.ifname} up")
|
||||
|
||||
def down():
|
||||
ip(f"link set dev {nsim.ifname} down")
|
||||
|
||||
def get_pp():
|
||||
pp_list = nf.page_pool_get({}, dump=True)
|
||||
return [pp for pp in pp_list if pp.get("ifindex") == nsim.ifindex]
|
||||
|
||||
# No page pools when down
|
||||
down()
|
||||
ksft_eq(len(get_pp()), 0)
|
||||
|
||||
# Up, empty page pool appears
|
||||
up()
|
||||
pp_list = get_pp()
|
||||
ksft_ge(len(pp_list), 0)
|
||||
refs = sum([pp["inflight"] for pp in pp_list])
|
||||
ksft_eq(refs, 0)
|
||||
|
||||
# Down, it disappears, again
|
||||
down()
|
||||
pp_list = get_pp()
|
||||
ksft_eq(len(pp_list), 0)
|
||||
|
||||
# Up, allocate a page
|
||||
up()
|
||||
nsim.dfs_write("pp_hold", "y")
|
||||
pp_list = nf.page_pool_get({}, dump=True)
|
||||
refs = sum([pp["inflight"] for pp in pp_list if pp.get("ifindex") == nsim.ifindex])
|
||||
ksft_ge(refs, 1)
|
||||
|
||||
# Now let's leak a page
|
||||
down()
|
||||
pp_list = get_pp()
|
||||
ksft_eq(len(pp_list), 1)
|
||||
refs = sum([pp["inflight"] for pp in pp_list])
|
||||
ksft_eq(refs, 1)
|
||||
attached = [pp for pp in pp_list if "detach-time" not in pp]
|
||||
ksft_eq(len(attached), 0)
|
||||
|
||||
# New pp can get created, and we'll have two
|
||||
up()
|
||||
pp_list = get_pp()
|
||||
attached = [pp for pp in pp_list if "detach-time" not in pp]
|
||||
detached = [pp for pp in pp_list if "detach-time" in pp]
|
||||
ksft_eq(len(attached), 1)
|
||||
ksft_eq(len(detached), 1)
|
||||
|
||||
# Free the old page and the old pp is gone
|
||||
nsim.dfs_write("pp_hold", "n")
|
||||
# Freeing check is once a second so we may need to retry
|
||||
ksft_busy_wait(lambda: len(get_pp()) == 1, deadline=2)
|
||||
|
||||
# And down...
|
||||
down()
|
||||
ksft_eq(len(get_pp()), 0)
|
||||
|
||||
# Last, leave the page hanging for destroy, nothing to check
|
||||
# we're trying to exercise the orphaning path in the kernel
|
||||
up()
|
||||
nsim.dfs_write("pp_hold", "y")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
nf = NetdevFamily()
|
||||
ksft_run([empty_check, lo_check], args=(nf, ))
|
||||
ksft_run([empty_check, lo_check, page_pool_check],
|
||||
args=(nf, ))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user