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:
Greg Kroah-Hartman
2024-07-30 08:34:00 +00:00
31 changed files with 719 additions and 204 deletions
+23 -16
View File
@@ -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
View File
@@ -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);
+22 -15
View File
@@ -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++) {
+32 -17
View File
@@ -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);
+27 -11
View File
@@ -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;
+2 -1
View File
@@ -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;
+2 -1
View File
@@ -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;
+65 -46
View File
@@ -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;
+4 -8
View File
@@ -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);
}
+2 -3
View File
@@ -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,
+4 -1
View File
@@ -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;
}
+93
View File
@@ -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);
}
+4
View File
@@ -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;
};
+3 -1
View File
@@ -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"
+23 -26
View File
@@ -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
+13 -3
View File
@@ -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=""
+29 -12
View File
@@ -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
+15 -1
View File
@@ -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)
+74 -2
View File
@@ -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__":