Merge c31bd5b6ff ("Merge branch 'rtl8226b-serdes-switching'") into android-mainline
Steps on the way to 6.10-rc1 Change-Id: I9072485af6d838d26eb2e3b7a76c09555481efc9 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -861,24 +861,27 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
|
||||
}
|
||||
}
|
||||
|
||||
static struct phylink_pcs *mv88e6xxx_mac_select_pcs(struct dsa_switch *ds,
|
||||
int port,
|
||||
phy_interface_t interface)
|
||||
static struct phylink_pcs *
|
||||
mv88e6xxx_mac_select_pcs(struct phylink_config *config,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mv88e6xxx_chip *chip = dp->ds->priv;
|
||||
struct phylink_pcs *pcs = ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
if (chip->info->ops->pcs_ops)
|
||||
pcs = chip->info->ops->pcs_ops->pcs_select(chip, port,
|
||||
pcs = chip->info->ops->pcs_ops->pcs_select(chip, dp->index,
|
||||
interface);
|
||||
|
||||
return pcs;
|
||||
}
|
||||
|
||||
static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port,
|
||||
static int mv88e6xxx_mac_prepare(struct phylink_config *config,
|
||||
unsigned int mode, phy_interface_t interface)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mv88e6xxx_chip *chip = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
/* In inband mode, the link may come up at any time while the link
|
||||
@@ -897,11 +900,13 @@ static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
|
||||
static void mv88e6xxx_mac_config(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mv88e6xxx_chip *chip = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
@@ -917,13 +922,15 @@ err_unlock:
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
if (err && err != -EOPNOTSUPP)
|
||||
dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
|
||||
dev_err(chip->dev, "p%d: failed to configure MAC/PCS\n", port);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port,
|
||||
static int mv88e6xxx_mac_finish(struct phylink_config *config,
|
||||
unsigned int mode, phy_interface_t interface)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mv88e6xxx_chip *chip = dp->ds->priv;
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
/* Undo the forced down state above after completing configuration
|
||||
@@ -947,12 +954,14 @@ static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
|
||||
static void mv88e6xxx_mac_link_down(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mv88e6xxx_chip *chip = dp->ds->priv;
|
||||
const struct mv88e6xxx_ops *ops;
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
ops = chip->info->ops;
|
||||
@@ -975,14 +984,16 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
|
||||
"p%d: failed to force MAC link down\n", port);
|
||||
}
|
||||
|
||||
static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
|
||||
unsigned int mode, phy_interface_t interface,
|
||||
static void mv88e6xxx_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 mv88e6xxx_chip *chip = ds->priv;
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct mv88e6xxx_chip *chip = dp->ds->priv;
|
||||
const struct mv88e6xxx_ops *ops;
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
ops = chip->info->ops;
|
||||
@@ -1008,7 +1019,7 @@ error:
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
if (err && err != -EOPNOTSUPP)
|
||||
dev_err(ds->dev,
|
||||
dev_err(chip->dev,
|
||||
"p%d: failed to configure MAC link up\n", port);
|
||||
}
|
||||
|
||||
@@ -6993,6 +7004,15 @@ static int mv88e6xxx_crosschip_lag_leave(struct dsa_switch *ds, int sw_index,
|
||||
return err_sync ? : err_pvt;
|
||||
}
|
||||
|
||||
static const struct phylink_mac_ops mv88e6xxx_phylink_mac_ops = {
|
||||
.mac_select_pcs = mv88e6xxx_mac_select_pcs,
|
||||
.mac_prepare = mv88e6xxx_mac_prepare,
|
||||
.mac_config = mv88e6xxx_mac_config,
|
||||
.mac_finish = mv88e6xxx_mac_finish,
|
||||
.mac_link_down = mv88e6xxx_mac_link_down,
|
||||
.mac_link_up = mv88e6xxx_mac_link_up,
|
||||
};
|
||||
|
||||
static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.get_tag_protocol = mv88e6xxx_get_tag_protocol,
|
||||
.change_tag_protocol = mv88e6xxx_change_tag_protocol,
|
||||
@@ -7001,12 +7021,6 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.port_setup = mv88e6xxx_port_setup,
|
||||
.port_teardown = mv88e6xxx_port_teardown,
|
||||
.phylink_get_caps = mv88e6xxx_get_caps,
|
||||
.phylink_mac_select_pcs = mv88e6xxx_mac_select_pcs,
|
||||
.phylink_mac_prepare = mv88e6xxx_mac_prepare,
|
||||
.phylink_mac_config = mv88e6xxx_mac_config,
|
||||
.phylink_mac_finish = mv88e6xxx_mac_finish,
|
||||
.phylink_mac_link_down = mv88e6xxx_mac_link_down,
|
||||
.phylink_mac_link_up = mv88e6xxx_mac_link_up,
|
||||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_eth_mac_stats = mv88e6xxx_get_eth_mac_stats,
|
||||
@@ -7075,6 +7089,7 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
|
||||
ds->priv = chip;
|
||||
ds->dev = dev;
|
||||
ds->ops = &mv88e6xxx_switch_ops;
|
||||
ds->phylink_mac_ops = &mv88e6xxx_phylink_mac_ops;
|
||||
ds->ageing_time_min = chip->info->age_time_coeff;
|
||||
ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <net/ipv6.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
#include "chcr_ktls.h"
|
||||
|
||||
static LIST_HEAD(uld_ctx_list);
|
||||
@@ -1658,7 +1659,7 @@ static void chcr_ktls_copy_record_in_skb(struct sk_buff *nskb,
|
||||
for (i = 0; i < record->num_frags; i++) {
|
||||
skb_shinfo(nskb)->frags[i] = record->frags[i];
|
||||
/* increase the frag ref count */
|
||||
__skb_frag_ref(&skb_shinfo(nskb)->frags[i]);
|
||||
__skb_frag_ref(&skb_shinfo(nskb)->frags[i], nskb->pp_recycle);
|
||||
}
|
||||
|
||||
skb_shinfo(nskb)->nr_frags = record->num_frags;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <linux/mii.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
||||
@@ -273,6 +273,40 @@ out:
|
||||
kvfree(out);
|
||||
}
|
||||
|
||||
static int mlx5e_rep_query_aggr_q_counter(struct mlx5_core_dev *dev, int vport, void *out)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(query_q_counter_in)] = {};
|
||||
|
||||
MLX5_SET(query_q_counter_in, in, opcode, MLX5_CMD_OP_QUERY_Q_COUNTER);
|
||||
MLX5_SET(query_q_counter_in, in, other_vport, 1);
|
||||
MLX5_SET(query_q_counter_in, in, vport_number, vport);
|
||||
MLX5_SET(query_q_counter_in, in, aggregate, 1);
|
||||
|
||||
return mlx5_cmd_exec_inout(dev, query_q_counter, in, out);
|
||||
}
|
||||
|
||||
static void mlx5e_rep_update_vport_q_counter(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_rep_stats *rep_stats = &priv->stats.rep_stats;
|
||||
u32 out[MLX5_ST_SZ_DW(query_q_counter_out)] = {};
|
||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||
struct mlx5_eswitch_rep *rep = rpriv->rep;
|
||||
int err;
|
||||
|
||||
if (!MLX5_CAP_GEN(priv->mdev, q_counter_other_vport) ||
|
||||
!MLX5_CAP_GEN(priv->mdev, q_counter_aggregation))
|
||||
return;
|
||||
|
||||
err = mlx5e_rep_query_aggr_q_counter(priv->mdev, rep->vport, out);
|
||||
if (err) {
|
||||
netdev_warn(priv->netdev, "failed reading stats on vport %d, error %d\n",
|
||||
rep->vport, err);
|
||||
return;
|
||||
}
|
||||
|
||||
rep_stats->rx_vport_out_of_buffer = MLX5_GET(query_q_counter_out, out, out_of_buffer);
|
||||
}
|
||||
|
||||
static void mlx5e_rep_get_strings(struct net_device *dev,
|
||||
u32 stringset, u8 *data)
|
||||
{
|
||||
@@ -1229,6 +1263,12 @@ static int mlx5e_update_rep_rx(struct mlx5e_priv *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mlx5e_rep_stats_update_ndo_stats(struct mlx5e_priv *priv)
|
||||
{
|
||||
mlx5e_stats_update_ndo_stats(priv);
|
||||
mlx5e_rep_update_vport_q_counter(priv);
|
||||
}
|
||||
|
||||
static int mlx5e_rep_event_mpesw(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||
@@ -1421,7 +1461,7 @@ static const struct mlx5e_profile mlx5e_rep_profile = {
|
||||
.enable = mlx5e_rep_enable,
|
||||
.disable = mlx5e_rep_disable,
|
||||
.update_rx = mlx5e_update_rep_rx,
|
||||
.update_stats = mlx5e_stats_update_ndo_stats,
|
||||
.update_stats = mlx5e_rep_stats_update_ndo_stats,
|
||||
.rx_handlers = &mlx5e_rx_handlers_rep,
|
||||
.max_tc = 1,
|
||||
.stats_grps = mlx5e_rep_stats_grps,
|
||||
|
||||
@@ -484,6 +484,7 @@ struct mlx5e_rep_stats {
|
||||
u64 tx_vport_rdma_multicast_bytes;
|
||||
u64 vport_loopback_packets;
|
||||
u64 vport_loopback_bytes;
|
||||
u64 rx_vport_out_of_buffer;
|
||||
};
|
||||
|
||||
struct mlx5e_stats {
|
||||
@@ -504,6 +505,7 @@ static inline void mlx5e_stats_copy_rep_stats(struct rtnl_link_stats64 *vf_vport
|
||||
vf_vport->tx_packets = rep_stats->vport_tx_packets;
|
||||
vf_vport->rx_bytes = rep_stats->vport_rx_bytes;
|
||||
vf_vport->tx_bytes = rep_stats->vport_tx_bytes;
|
||||
vf_vport->rx_missed_errors = rep_stats->rx_vport_out_of_buffer;
|
||||
}
|
||||
|
||||
extern mlx5e_stats_grp_t mlx5e_nic_stats_grps[];
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/random.h>
|
||||
@@ -1999,7 +2000,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
|
||||
skb->len += hlen - swivel;
|
||||
|
||||
skb_frag_fill_page_desc(frag, page->buffer, off, hlen - swivel);
|
||||
__skb_frag_ref(frag);
|
||||
__skb_frag_ref(frag, skb->pp_recycle);
|
||||
|
||||
/* any more data? */
|
||||
if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
|
||||
@@ -2023,7 +2024,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
|
||||
frag++;
|
||||
|
||||
skb_frag_fill_page_desc(frag, page->buffer, 0, hlen);
|
||||
__skb_frag_ref(frag);
|
||||
__skb_frag_ref(frag, skb->pp_recycle);
|
||||
RX_USED_ADD(page, hlen + cp->crc_size);
|
||||
}
|
||||
|
||||
|
||||
+298
-26
@@ -54,6 +54,25 @@
|
||||
RTL8201F_ISR_LINK)
|
||||
#define RTL8201F_IER 0x13
|
||||
|
||||
#define RTL822X_VND1_SERDES_OPTION 0x697a
|
||||
#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0)
|
||||
#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0
|
||||
#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2
|
||||
|
||||
#define RTL822X_VND1_SERDES_CTRL3 0x7580
|
||||
#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0)
|
||||
#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02
|
||||
#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16
|
||||
|
||||
/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45
|
||||
* is set, they cannot be accessed by C45-over-C22.
|
||||
*/
|
||||
#define RTL822X_VND2_GBCR 0xa412
|
||||
|
||||
#define RTL822X_VND2_GANLPAR 0xa414
|
||||
|
||||
#define RTL822X_VND2_PHYSR 0xa434
|
||||
|
||||
#define RTL8366RB_POWER_SAVE 0x15
|
||||
#define RTL8366RB_POWER_SAVE_ON BIT(12)
|
||||
|
||||
@@ -64,6 +83,9 @@
|
||||
|
||||
#define RTL_GENERIC_PHYID 0x001cc800
|
||||
#define RTL_8211FVD_PHYID 0x001cc878
|
||||
#define RTL_8221B_VB_CG 0x001cc849
|
||||
#define RTL_8221B_VN_CG 0x001cc84a
|
||||
#define RTL_8251B 0x001cc862
|
||||
|
||||
MODULE_DESCRIPTION("Realtek PHY driver");
|
||||
MODULE_AUTHOR("Johnson Leung");
|
||||
@@ -531,17 +553,8 @@ static int rtl8366rb_config_init(struct phy_device *phydev)
|
||||
}
|
||||
|
||||
/* get actual speed to cover the downshift case */
|
||||
static int rtlgen_get_speed(struct phy_device *phydev)
|
||||
static void rtlgen_decode_speed(struct phy_device *phydev, int val)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (!phydev->link)
|
||||
return 0;
|
||||
|
||||
val = phy_read_paged(phydev, 0xa43, 0x12);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
switch (val & RTLGEN_SPEED_MASK) {
|
||||
case 0x0000:
|
||||
phydev->speed = SPEED_10;
|
||||
@@ -564,19 +577,26 @@ static int rtlgen_get_speed(struct phy_device *phydev)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtlgen_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
int ret, val;
|
||||
|
||||
ret = genphy_read_status(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return rtlgen_get_speed(phydev);
|
||||
if (!phydev->link)
|
||||
return 0;
|
||||
|
||||
val = phy_read_paged(phydev, 0xa43, 0x12);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
rtlgen_decode_speed(phydev, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
|
||||
@@ -659,6 +679,84 @@ static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl822xb_config_init(struct phy_device *phydev)
|
||||
{
|
||||
bool has_2500, has_sgmii;
|
||||
u16 mode;
|
||||
int ret;
|
||||
|
||||
has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
|
||||
phydev->host_interfaces) ||
|
||||
phydev->interface == PHY_INTERFACE_MODE_2500BASEX;
|
||||
|
||||
has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII,
|
||||
phydev->host_interfaces) ||
|
||||
phydev->interface == PHY_INTERFACE_MODE_SGMII;
|
||||
|
||||
/* fill in possible interfaces */
|
||||
__assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces,
|
||||
has_2500);
|
||||
__assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces,
|
||||
has_sgmii);
|
||||
|
||||
if (!has_2500 && !has_sgmii)
|
||||
return 0;
|
||||
|
||||
/* determine SerDes option mode */
|
||||
if (has_2500 && !has_sgmii) {
|
||||
mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX;
|
||||
phydev->rate_matching = RATE_MATCH_PAUSE;
|
||||
} else {
|
||||
mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII;
|
||||
phydev->rate_matching = RATE_MATCH_NONE;
|
||||
}
|
||||
|
||||
/* the following sequence with magic numbers sets up the SerDes
|
||||
* option mode
|
||||
*/
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1,
|
||||
RTL822X_VND1_SERDES_OPTION,
|
||||
RTL822X_VND1_SERDES_OPTION_MODE_MASK,
|
||||
mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
|
||||
}
|
||||
|
||||
static int rtl822xb_get_rate_matching(struct phy_device *phydev,
|
||||
phy_interface_t iface)
|
||||
{
|
||||
int val;
|
||||
|
||||
/* Only rate matching at 2500base-x */
|
||||
if (iface != PHY_INTERFACE_MODE_2500BASEX)
|
||||
return RATE_MATCH_NONE;
|
||||
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_OPTION);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
if ((val & RTL822X_VND1_SERDES_OPTION_MODE_MASK) ==
|
||||
RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX)
|
||||
return RATE_MATCH_PAUSE;
|
||||
|
||||
/* RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII */
|
||||
return RATE_MATCH_NONE;
|
||||
}
|
||||
|
||||
static int rtl822x_get_features(struct phy_device *phydev)
|
||||
{
|
||||
int val;
|
||||
@@ -695,10 +793,30 @@ static int rtl822x_config_aneg(struct phy_device *phydev)
|
||||
return __genphy_config_aneg(phydev, ret);
|
||||
}
|
||||
|
||||
static void rtl822xb_update_interface(struct phy_device *phydev)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (!phydev->link)
|
||||
return;
|
||||
|
||||
/* Change interface according to serdes mode */
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3);
|
||||
if (val < 0)
|
||||
return;
|
||||
|
||||
switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) {
|
||||
case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX:
|
||||
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
|
||||
break;
|
||||
case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII:
|
||||
phydev->interface = PHY_INTERFACE_MODE_SGMII;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rtl822x_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (phydev->autoneg == AUTONEG_ENABLE) {
|
||||
int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
|
||||
|
||||
@@ -709,11 +827,99 @@ static int rtl822x_read_status(struct phy_device *phydev)
|
||||
lpadv);
|
||||
}
|
||||
|
||||
ret = genphy_read_status(phydev);
|
||||
return rtlgen_read_status(phydev);
|
||||
}
|
||||
|
||||
static int rtl822xb_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rtl822x_read_status(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return rtlgen_get_speed(phydev);
|
||||
rtl822xb_update_interface(phydev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl822x_c45_get_features(struct phy_device *phydev)
|
||||
{
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
|
||||
phydev->supported);
|
||||
|
||||
return genphy_c45_pma_read_abilities(phydev);
|
||||
}
|
||||
|
||||
static int rtl822x_c45_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
bool changed = false;
|
||||
int ret, val;
|
||||
|
||||
if (phydev->autoneg == AUTONEG_DISABLE)
|
||||
return genphy_c45_pma_setup_forced(phydev);
|
||||
|
||||
ret = genphy_c45_an_config_aneg(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret > 0)
|
||||
changed = true;
|
||||
|
||||
val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
|
||||
|
||||
/* Vendor register as C45 has no standardized support for 1000BaseT */
|
||||
ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR,
|
||||
ADVERTISE_1000FULL, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret > 0)
|
||||
changed = true;
|
||||
|
||||
return genphy_c45_check_and_restart_aneg(phydev, changed);
|
||||
}
|
||||
|
||||
static int rtl822x_c45_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int ret, val;
|
||||
|
||||
ret = genphy_c45_read_status(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Vendor register as C45 has no standardized support for 1000BaseT */
|
||||
if (phydev->autoneg == AUTONEG_ENABLE) {
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||
RTL822X_VND2_GANLPAR);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
|
||||
}
|
||||
|
||||
if (!phydev->link)
|
||||
return 0;
|
||||
|
||||
/* Read actual speed from vendor register. */
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_PHYSR);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
rtlgen_decode_speed(phydev, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl822xb_c45_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rtl822x_c45_read_status(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
rtl822xb_update_interface(phydev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
|
||||
@@ -739,6 +945,35 @@ static int rtl8226_match_phy_device(struct phy_device *phydev)
|
||||
rtlgen_supports_2_5gbps(phydev);
|
||||
}
|
||||
|
||||
static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
|
||||
bool is_c45)
|
||||
{
|
||||
if (phydev->is_c45)
|
||||
return is_c45 && (id == phydev->c45_ids.device_ids[1]);
|
||||
else
|
||||
return !is_c45 && (id == phydev->phy_id);
|
||||
}
|
||||
|
||||
static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
|
||||
{
|
||||
return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
|
||||
}
|
||||
|
||||
static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev)
|
||||
{
|
||||
return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
|
||||
}
|
||||
|
||||
static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev)
|
||||
{
|
||||
return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false);
|
||||
}
|
||||
|
||||
static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev)
|
||||
{
|
||||
return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
|
||||
}
|
||||
|
||||
static int rtlgen_resume(struct phy_device *phydev)
|
||||
{
|
||||
int ret = genphy_resume(phydev);
|
||||
@@ -749,6 +984,15 @@ static int rtlgen_resume(struct phy_device *phydev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtlgen_c45_resume(struct phy_device *phydev)
|
||||
{
|
||||
int ret = genphy_c45_pma_resume(phydev);
|
||||
|
||||
msleep(20);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl9000a_config_init(struct phy_device *phydev)
|
||||
{
|
||||
phydev->autoneg = AUTONEG_DISABLE;
|
||||
@@ -988,7 +1232,9 @@ static struct phy_driver realtek_drvs[] = {
|
||||
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.read_status = rtl822x_read_status,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
@@ -1010,31 +1256,57 @@ static struct phy_driver realtek_drvs[] = {
|
||||
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.read_status = rtl822x_read_status,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc849),
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY",
|
||||
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.read_status = rtl822x_read_status,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc84a),
|
||||
.name = "RTL8221B-VM-CG 2.5Gbps PHY",
|
||||
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.get_features = rtl822x_c45_get_features,
|
||||
.config_aneg = rtl822x_c45_config_aneg,
|
||||
.read_status = rtl822xb_c45_read_status,
|
||||
.suspend = genphy_c45_pma_suspend,
|
||||
.resume = rtlgen_c45_resume,
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.read_status = rtl822x_read_status,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.read_status = rtl822xb_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.get_features = rtl822x_c45_get_features,
|
||||
.config_aneg = rtl822x_c45_config_aneg,
|
||||
.read_status = rtl822xb_c45_read_status,
|
||||
.suspend = genphy_c45_pma_suspend,
|
||||
.resume = rtlgen_c45_resume,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc862),
|
||||
.name = "RTL8251B 5Gbps PHY",
|
||||
|
||||
@@ -506,6 +506,7 @@ static const struct sfp_quirk sfp_quirks[] = {
|
||||
SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
|
||||
SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
|
||||
SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),
|
||||
SFP_QUIRK_F("Turris", "RTSFP-2.5G", sfp_fixup_rollball),
|
||||
SFP_QUIRK_F("Turris", "RTSFP-10", sfp_fixup_rollball),
|
||||
SFP_QUIRK_F("Turris", "RTSFP-10G", sfp_fixup_rollball),
|
||||
};
|
||||
|
||||
@@ -121,7 +121,6 @@ static const struct net_device_ops qmimux_netdev_ops = {
|
||||
.ndo_open = qmimux_open,
|
||||
.ndo_stop = qmimux_stop,
|
||||
.ndo_start_xmit = qmimux_start_xmit,
|
||||
.ndo_get_stats64 = dev_get_tstats64,
|
||||
};
|
||||
|
||||
static void qmimux_setup(struct net_device *dev)
|
||||
@@ -133,6 +132,7 @@ static void qmimux_setup(struct net_device *dev)
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
|
||||
dev->netdev_ops = &qmimux_netdev_ops;
|
||||
dev->mtu = 1500;
|
||||
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
|
||||
dev->needs_free_netdev = true;
|
||||
}
|
||||
|
||||
@@ -257,12 +257,6 @@ static int qmimux_register_device(struct net_device *real_dev, u8 mux_id)
|
||||
priv->mux_id = mux_id;
|
||||
priv->real_dev = real_dev;
|
||||
|
||||
new_dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
||||
if (!new_dev->tstats) {
|
||||
err = -ENOBUFS;
|
||||
goto out_free_newdev;
|
||||
}
|
||||
|
||||
new_dev->sysfs_groups[0] = &qmi_wwan_sysfs_qmimux_attr_group;
|
||||
|
||||
err = register_netdevice(new_dev);
|
||||
@@ -295,7 +289,6 @@ static void qmimux_unregister_device(struct net_device *dev,
|
||||
struct qmimux_priv *priv = netdev_priv(dev);
|
||||
struct net_device *real_dev = priv->real_dev;
|
||||
|
||||
free_percpu(dev->tstats);
|
||||
netdev_upper_dev_unlink(real_dev, dev);
|
||||
unregister_netdevice_queue(dev, head);
|
||||
|
||||
@@ -644,7 +637,6 @@ static const struct net_device_ops qmi_wwan_netdev_ops = {
|
||||
.ndo_start_xmit = usbnet_start_xmit,
|
||||
.ndo_tx_timeout = usbnet_tx_timeout,
|
||||
.ndo_change_mtu = usbnet_change_mtu,
|
||||
.ndo_get_stats64 = dev_get_tstats64,
|
||||
.ndo_set_mac_address = qmi_wwan_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
@@ -1733,6 +1733,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
||||
dev->hard_mtu = net->mtu + net->hard_header_len;
|
||||
net->min_mtu = 0;
|
||||
net->max_mtu = ETH_MAX_MTU;
|
||||
net->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
|
||||
|
||||
net->netdev_ops = &usbnet_netdev_ops;
|
||||
net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@
|
||||
#include <linux/ptr_ring.h>
|
||||
#include <linux/bpf_trace.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
|
||||
#define DRV_NAME "veth"
|
||||
@@ -716,7 +717,7 @@ static void veth_xdp_get(struct xdp_buff *xdp)
|
||||
return;
|
||||
|
||||
for (i = 0; i < sinfo->nr_frags; i++)
|
||||
__skb_frag_ref(&sinfo->frags[i]);
|
||||
__skb_frag_ref(&sinfo->frags[i], false);
|
||||
}
|
||||
|
||||
static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include <net/tcp.h>
|
||||
|
||||
|
||||
@@ -3512,73 +3512,10 @@ static inline struct page *skb_frag_page(const skb_frag_t *frag)
|
||||
return netmem_to_page(frag->netmem);
|
||||
}
|
||||
|
||||
/**
|
||||
* __skb_frag_ref - take an addition reference on a paged fragment.
|
||||
* @frag: the paged fragment
|
||||
*
|
||||
* Takes an additional reference on the paged fragment @frag.
|
||||
*/
|
||||
static inline void __skb_frag_ref(skb_frag_t *frag)
|
||||
{
|
||||
get_page(skb_frag_page(frag));
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_frag_ref - take an addition reference on a paged fragment of an skb.
|
||||
* @skb: the buffer
|
||||
* @f: the fragment offset.
|
||||
*
|
||||
* Takes an additional reference on the @f'th paged fragment of @skb.
|
||||
*/
|
||||
static inline void skb_frag_ref(struct sk_buff *skb, int f)
|
||||
{
|
||||
__skb_frag_ref(&skb_shinfo(skb)->frags[f]);
|
||||
}
|
||||
|
||||
int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
|
||||
unsigned int headroom);
|
||||
int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
|
||||
struct bpf_prog *prog);
|
||||
bool napi_pp_put_page(struct page *page);
|
||||
|
||||
static inline void
|
||||
skb_page_unref(struct page *page, bool recycle)
|
||||
{
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
if (recycle && napi_pp_put_page(page))
|
||||
return;
|
||||
#endif
|
||||
put_page(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* __skb_frag_unref - release a reference on a paged fragment.
|
||||
* @frag: the paged fragment
|
||||
* @recycle: recycle the page if allocated via page_pool
|
||||
*
|
||||
* Releases a reference on the paged fragment @frag
|
||||
* or recycles the page via the page_pool API.
|
||||
*/
|
||||
static inline void __skb_frag_unref(skb_frag_t *frag, bool recycle)
|
||||
{
|
||||
skb_page_unref(skb_frag_page(frag), recycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_frag_unref - release a reference on a paged fragment of an skb.
|
||||
* @skb: the buffer
|
||||
* @f: the fragment offset
|
||||
*
|
||||
* Releases a reference on the @f'th paged fragment of @skb.
|
||||
*/
|
||||
static inline void skb_frag_unref(struct sk_buff *skb, int f)
|
||||
{
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
|
||||
if (!skb_zcopy_managed(skb))
|
||||
__skb_frag_unref(&shinfo->frags[f], skb->pp_recycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_frag_address - gets the address of the data contained in a paged fragment
|
||||
* @frag: the paged fragment buffer
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Skb ref helpers.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SKBUFF_REF_H
|
||||
#define _LINUX_SKBUFF_REF_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
static inline bool is_pp_page(struct page *page)
|
||||
{
|
||||
return (page->pp_magic & ~0x3UL) == PP_SIGNATURE;
|
||||
}
|
||||
|
||||
static inline bool napi_pp_get_page(struct page *page)
|
||||
{
|
||||
page = compound_head(page);
|
||||
|
||||
if (!is_pp_page(page))
|
||||
return false;
|
||||
|
||||
page_pool_ref_page(page);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void skb_page_ref(struct page *page, bool recycle)
|
||||
{
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
if (recycle && napi_pp_get_page(page))
|
||||
return;
|
||||
#endif
|
||||
get_page(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* __skb_frag_ref - take an addition reference on a paged fragment.
|
||||
* @frag: the paged fragment
|
||||
* @recycle: skb->pp_recycle param of the parent skb. False if no parent skb.
|
||||
*
|
||||
* Takes an additional reference on the paged fragment @frag. Obtains the
|
||||
* correct reference count depending on whether skb->pp_recycle is set and
|
||||
* whether the frag is a page pool frag.
|
||||
*/
|
||||
static inline void __skb_frag_ref(skb_frag_t *frag, bool recycle)
|
||||
{
|
||||
skb_page_ref(skb_frag_page(frag), recycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_frag_ref - take an addition reference on a paged fragment of an skb.
|
||||
* @skb: the buffer
|
||||
* @f: the fragment offset.
|
||||
*
|
||||
* Takes an additional reference on the @f'th paged fragment of @skb.
|
||||
*/
|
||||
static inline void skb_frag_ref(struct sk_buff *skb, int f)
|
||||
{
|
||||
__skb_frag_ref(&skb_shinfo(skb)->frags[f], skb->pp_recycle);
|
||||
}
|
||||
|
||||
bool napi_pp_put_page(struct page *page);
|
||||
|
||||
static inline void
|
||||
skb_page_unref(struct page *page, bool recycle)
|
||||
{
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
if (recycle && napi_pp_put_page(page))
|
||||
return;
|
||||
#endif
|
||||
put_page(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* __skb_frag_unref - release a reference on a paged fragment.
|
||||
* @frag: the paged fragment
|
||||
* @recycle: recycle the page if allocated via page_pool
|
||||
*
|
||||
* Releases a reference on the paged fragment @frag
|
||||
* or recycles the page via the page_pool API.
|
||||
*/
|
||||
static inline void __skb_frag_unref(skb_frag_t *frag, bool recycle)
|
||||
{
|
||||
skb_page_unref(skb_frag_page(frag), recycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_frag_unref - release a reference on a paged fragment of an skb.
|
||||
* @skb: the buffer
|
||||
* @f: the fragment offset
|
||||
*
|
||||
* Releases a reference on the @f'th paged fragment of @skb.
|
||||
*/
|
||||
static inline void skb_frag_unref(struct sk_buff *skb, int f)
|
||||
{
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
|
||||
if (!skb_zcopy_managed(skb))
|
||||
__skb_frag_unref(&shinfo->frags[f], skb->pp_recycle);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_SKBUFF_REF_H */
|
||||
@@ -327,6 +327,12 @@ struct dsa_port {
|
||||
};
|
||||
};
|
||||
|
||||
static inline struct dsa_port *
|
||||
dsa_phylink_to_port(struct phylink_config *config)
|
||||
{
|
||||
return container_of(config, struct dsa_port, pl_config);
|
||||
}
|
||||
|
||||
/* TODO: ideally DSA ports would have a single dp->link_dp member,
|
||||
* and no dst->rtable nor this struct dsa_link would be needed,
|
||||
* but this would require some more complex tree walking,
|
||||
@@ -451,6 +457,11 @@ struct dsa_switch {
|
||||
*/
|
||||
const struct dsa_switch_ops *ops;
|
||||
|
||||
/*
|
||||
* Allow a DSA switch driver to override the phylink MAC ops
|
||||
*/
|
||||
const struct phylink_mac_ops *phylink_mac_ops;
|
||||
|
||||
/*
|
||||
* User mii_bus and devices for the individual ports.
|
||||
*/
|
||||
|
||||
@@ -345,7 +345,7 @@ static inline bool flow_action_has_entries(const struct flow_action *action)
|
||||
* flow_offload_has_one_action() - check if exactly one action is present
|
||||
* @action: tc filter flow offload action
|
||||
*
|
||||
* Returns true if exactly one action is present.
|
||||
* Return: true if exactly one action is present.
|
||||
*/
|
||||
static inline bool flow_offload_has_one_action(const struct flow_action *action)
|
||||
{
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#include <linux/cache.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#define RTO_ONLINK 0x01
|
||||
|
||||
static inline __u8 ip_sock_rt_scope(const struct sock *sk)
|
||||
{
|
||||
if (sock_flag(sk, SOCK_LOCALROUTE))
|
||||
|
||||
@@ -58,6 +58,10 @@ struct mptcp_info {
|
||||
__u64 mptcpi_bytes_received;
|
||||
__u64 mptcpi_bytes_acked;
|
||||
__u8 mptcpi_subflows_total;
|
||||
__u8 reserved[3];
|
||||
__u32 mptcpi_last_data_sent;
|
||||
__u32 mptcpi_last_data_recv;
|
||||
__u32 mptcpi_last_ack_recv;
|
||||
};
|
||||
|
||||
/* MPTCP Reset reason codes, rfc8684 */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <net/dst_metadata.h>
|
||||
#include <net/busy_poll.h>
|
||||
#include <trace/events/net.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#define MAX_GRO_SKBS 8
|
||||
|
||||
|
||||
+5
-42
@@ -51,6 +51,7 @@
|
||||
#endif
|
||||
#include <linux/string.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
#include <linux/splice.h>
|
||||
#include <linux/cache.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
@@ -906,11 +907,6 @@ static void skb_clone_fraglist(struct sk_buff *skb)
|
||||
skb_get(list);
|
||||
}
|
||||
|
||||
static bool is_pp_page(struct page *page)
|
||||
{
|
||||
return (page->pp_magic & ~0x3UL) == PP_SIGNATURE;
|
||||
}
|
||||
|
||||
int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
|
||||
unsigned int headroom)
|
||||
{
|
||||
@@ -1032,37 +1028,6 @@ static bool skb_pp_recycle(struct sk_buff *skb, void *data)
|
||||
return napi_pp_put_page(virt_to_page(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_pp_frag_ref() - Increase fragment references of a page pool aware skb
|
||||
* @skb: page pool aware skb
|
||||
*
|
||||
* Increase the fragment reference count (pp_ref_count) of a skb. This is
|
||||
* intended to gain fragment references only for page pool aware skbs,
|
||||
* i.e. when skb->pp_recycle is true, and not for fragments in a
|
||||
* non-pp-recycling skb. It has a fallback to increase references on normal
|
||||
* pages, as page pool aware skbs may also have normal page fragments.
|
||||
*/
|
||||
static int skb_pp_frag_ref(struct sk_buff *skb)
|
||||
{
|
||||
struct skb_shared_info *shinfo;
|
||||
struct page *head_page;
|
||||
int i;
|
||||
|
||||
if (!skb->pp_recycle)
|
||||
return -EINVAL;
|
||||
|
||||
shinfo = skb_shinfo(skb);
|
||||
|
||||
for (i = 0; i < shinfo->nr_frags; i++) {
|
||||
head_page = compound_head(skb_frag_page(&shinfo->frags[i]));
|
||||
if (likely(is_pp_page(head_page)))
|
||||
page_pool_ref_page(head_page);
|
||||
else
|
||||
page_ref_inc(head_page);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void skb_kfree_head(void *head, unsigned int end_offset)
|
||||
{
|
||||
if (end_offset == SKB_SMALL_HEAD_HEADROOM)
|
||||
@@ -4198,7 +4163,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
|
||||
to++;
|
||||
|
||||
} else {
|
||||
__skb_frag_ref(fragfrom);
|
||||
__skb_frag_ref(fragfrom, skb->pp_recycle);
|
||||
skb_frag_page_copy(fragto, fragfrom);
|
||||
skb_frag_off_copy(fragto, fragfrom);
|
||||
skb_frag_size_set(fragto, todo);
|
||||
@@ -4848,7 +4813,7 @@ normal:
|
||||
}
|
||||
|
||||
*nskb_frag = (i < 0) ? skb_head_frag_to_page_desc(frag_skb) : *frag;
|
||||
__skb_frag_ref(nskb_frag);
|
||||
__skb_frag_ref(nskb_frag, nskb->pp_recycle);
|
||||
size = skb_frag_size(nskb_frag);
|
||||
|
||||
if (pos < offset) {
|
||||
@@ -5979,10 +5944,8 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
|
||||
/* if the skb is not cloned this does nothing
|
||||
* since we set nr_frags to 0.
|
||||
*/
|
||||
if (skb_pp_frag_ref(from)) {
|
||||
for (i = 0; i < from_shinfo->nr_frags; i++)
|
||||
__skb_frag_ref(&from_shinfo->frags[i]);
|
||||
}
|
||||
for (i = 0; i < from_shinfo->nr_frags; i++)
|
||||
__skb_frag_ref(&from_shinfo->frags[i], from->pp_recycle);
|
||||
|
||||
to->truesize += delta;
|
||||
to->len += len;
|
||||
|
||||
@@ -1505,6 +1505,17 @@ static int dsa_switch_probe(struct dsa_switch *ds)
|
||||
if (!ds->num_ports)
|
||||
return -EINVAL;
|
||||
|
||||
if (ds->phylink_mac_ops) {
|
||||
if (ds->ops->phylink_mac_select_pcs ||
|
||||
ds->ops->phylink_mac_prepare ||
|
||||
ds->ops->phylink_mac_config ||
|
||||
ds->ops->phylink_mac_finish ||
|
||||
ds->ops->phylink_mac_link_down ||
|
||||
ds->ops->phylink_mac_link_up ||
|
||||
ds->ops->adjust_link)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (np) {
|
||||
err = dsa_switch_parse_of(ds, np);
|
||||
if (err)
|
||||
|
||||
+26
-12
@@ -1558,7 +1558,7 @@ static struct phylink_pcs *
|
||||
dsa_port_phylink_mac_select_pcs(struct phylink_config *config,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct phylink_pcs *pcs = ERR_PTR(-EOPNOTSUPP);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
@@ -1572,7 +1572,7 @@ static int dsa_port_phylink_mac_prepare(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
int err = 0;
|
||||
|
||||
@@ -1587,7 +1587,7 @@ static void dsa_port_phylink_mac_config(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (!ds->ops->phylink_mac_config)
|
||||
@@ -1600,7 +1600,7 @@ static int dsa_port_phylink_mac_finish(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
int err = 0;
|
||||
|
||||
@@ -1615,7 +1615,7 @@ static void dsa_port_phylink_mac_link_down(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct phy_device *phydev = NULL;
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
@@ -1638,7 +1638,7 @@ static void dsa_port_phylink_mac_link_up(struct phylink_config *config,
|
||||
int speed, int duplex,
|
||||
bool tx_pause, bool rx_pause)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (!ds->ops->phylink_mac_link_up) {
|
||||
@@ -1662,6 +1662,7 @@ static const struct phylink_mac_ops dsa_port_phylink_mac_ops = {
|
||||
|
||||
int dsa_port_phylink_create(struct dsa_port *dp)
|
||||
{
|
||||
const struct phylink_mac_ops *mac_ops;
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
phy_interface_t mode;
|
||||
struct phylink *pl;
|
||||
@@ -1685,8 +1686,12 @@ int dsa_port_phylink_create(struct dsa_port *dp)
|
||||
}
|
||||
}
|
||||
|
||||
pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn),
|
||||
mode, &dsa_port_phylink_mac_ops);
|
||||
mac_ops = &dsa_port_phylink_mac_ops;
|
||||
if (ds->phylink_mac_ops)
|
||||
mac_ops = ds->phylink_mac_ops;
|
||||
|
||||
pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), mode,
|
||||
mac_ops);
|
||||
if (IS_ERR(pl)) {
|
||||
pr_err("error creating PHYLINK: %ld\n", PTR_ERR(pl));
|
||||
return PTR_ERR(pl);
|
||||
@@ -1952,12 +1957,23 @@ static void dsa_shared_port_validate_of(struct dsa_port *dp,
|
||||
dn, dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index);
|
||||
}
|
||||
|
||||
static void dsa_shared_port_link_down(struct dsa_port *dp)
|
||||
{
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
|
||||
if (ds->phylink_mac_ops && ds->phylink_mac_ops->mac_link_down)
|
||||
ds->phylink_mac_ops->mac_link_down(&dp->pl_config, MLO_AN_FIXED,
|
||||
PHY_INTERFACE_MODE_NA);
|
||||
else if (ds->ops->phylink_mac_link_down)
|
||||
ds->ops->phylink_mac_link_down(ds, dp->index, MLO_AN_FIXED,
|
||||
PHY_INTERFACE_MODE_NA);
|
||||
}
|
||||
|
||||
int dsa_shared_port_link_register_of(struct dsa_port *dp)
|
||||
{
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
bool missing_link_description;
|
||||
bool missing_phy_mode;
|
||||
int port = dp->index;
|
||||
|
||||
dsa_shared_port_validate_of(dp, &missing_phy_mode,
|
||||
&missing_link_description);
|
||||
@@ -1973,9 +1989,7 @@ int dsa_shared_port_link_register_of(struct dsa_port *dp)
|
||||
"Skipping phylink registration for %s port %d\n",
|
||||
dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index);
|
||||
} else {
|
||||
if (ds->ops->phylink_mac_link_down)
|
||||
ds->ops->phylink_mac_link_down(ds, port,
|
||||
MLO_AN_FIXED, PHY_INTERFACE_MODE_NA);
|
||||
dsa_shared_port_link_down(dp);
|
||||
|
||||
return dsa_shared_port_phylink_register(dp);
|
||||
}
|
||||
|
||||
@@ -1072,6 +1072,7 @@ const struct proto_ops inet_stream_ops = {
|
||||
#endif
|
||||
.splice_eof = inet_splice_eof,
|
||||
.splice_read = tcp_splice_read,
|
||||
.set_peek_off = sk_set_peek_off,
|
||||
.read_sock = tcp_read_sock,
|
||||
.read_skb = tcp_read_skb,
|
||||
.sendmsg_locked = tcp_sendmsg_locked,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <net/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/espintcp.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include <linux/highmem.h>
|
||||
|
||||
|
||||
+1
-13
@@ -106,9 +106,6 @@
|
||||
|
||||
#include "fib_lookup.h"
|
||||
|
||||
#define RT_FL_TOS(oldflp4) \
|
||||
((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))
|
||||
|
||||
#define RT_GC_TIMEOUT (300*HZ)
|
||||
|
||||
#define DEFAULT_MIN_PMTU (512 + 20 + 20)
|
||||
@@ -498,15 +495,6 @@ void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
|
||||
}
|
||||
EXPORT_SYMBOL(__ip_select_ident);
|
||||
|
||||
static void ip_rt_fix_tos(struct flowi4 *fl4)
|
||||
{
|
||||
__u8 tos = RT_FL_TOS(fl4);
|
||||
|
||||
fl4->flowi4_tos = tos & IPTOS_RT_MASK;
|
||||
if (tos & RTO_ONLINK)
|
||||
fl4->flowi4_scope = RT_SCOPE_LINK;
|
||||
}
|
||||
|
||||
static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
|
||||
const struct sock *sk, const struct iphdr *iph,
|
||||
int oif, __u8 tos, u8 prot, u32 mark,
|
||||
@@ -2639,7 +2627,7 @@ struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
||||
struct rtable *rth;
|
||||
|
||||
fl4->flowi4_iif = LOOPBACK_IFINDEX;
|
||||
ip_rt_fix_tos(fl4);
|
||||
fl4->flowi4_tos &= IPTOS_RT_MASK;
|
||||
|
||||
rcu_read_lock();
|
||||
rth = ip_route_output_key_hash_rcu(net, fl4, &res, skb);
|
||||
|
||||
+10
-6
@@ -1419,8 +1419,6 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr *msg, int len)
|
||||
struct sk_buff *skb;
|
||||
int copied = 0, err = 0;
|
||||
|
||||
/* XXX -- need to support SO_PEEK_OFF */
|
||||
|
||||
skb_rbtree_walk(skb, &sk->tcp_rtx_queue) {
|
||||
err = skb_copy_datagram_msg(skb, 0, msg, skb->len);
|
||||
if (err)
|
||||
@@ -2331,6 +2329,7 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
int target; /* Read at least this many bytes */
|
||||
long timeo;
|
||||
struct sk_buff *skb, *last;
|
||||
u32 peek_offset = 0;
|
||||
u32 urg_hole = 0;
|
||||
|
||||
err = -ENOTCONN;
|
||||
@@ -2364,7 +2363,8 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
|
||||
seq = &tp->copied_seq;
|
||||
if (flags & MSG_PEEK) {
|
||||
peek_seq = tp->copied_seq;
|
||||
peek_offset = max(sk_peek_offset(sk, flags), 0);
|
||||
peek_seq = tp->copied_seq + peek_offset;
|
||||
seq = &peek_seq;
|
||||
}
|
||||
|
||||
@@ -2467,11 +2467,11 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
}
|
||||
|
||||
if ((flags & MSG_PEEK) &&
|
||||
(peek_seq - copied - urg_hole != tp->copied_seq)) {
|
||||
(peek_seq - peek_offset - copied - urg_hole != tp->copied_seq)) {
|
||||
net_dbg_ratelimited("TCP(%s:%d): Application bug, race in MSG_PEEK\n",
|
||||
current->comm,
|
||||
task_pid_nr(current));
|
||||
peek_seq = tp->copied_seq;
|
||||
peek_seq = tp->copied_seq + peek_offset;
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -2512,7 +2512,10 @@ found_ok_skb:
|
||||
WRITE_ONCE(*seq, *seq + used);
|
||||
copied += used;
|
||||
len -= used;
|
||||
|
||||
if (flags & MSG_PEEK)
|
||||
sk_peek_offset_fwd(sk, used);
|
||||
else
|
||||
sk_peek_offset_bwd(sk, used);
|
||||
tcp_rcv_space_adjust(sk);
|
||||
|
||||
skip_copy:
|
||||
@@ -3013,6 +3016,7 @@ int tcp_disconnect(struct sock *sk, int flags)
|
||||
__skb_queue_purge(&sk->sk_receive_queue);
|
||||
WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
|
||||
WRITE_ONCE(tp->urg_data, 0);
|
||||
sk_set_peek_off(sk, -1);
|
||||
tcp_write_queue_purge(sk);
|
||||
tcp_fastopen_active_disable_ofo_check(sk);
|
||||
skb_rbtree_purge(&tp->out_of_order_queue);
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/static_key.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include <trace/events/tcp.h>
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <net/tcp.h>
|
||||
#include <net/espintcp.h>
|
||||
#include <net/inet6_hashtables.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include <linux/highmem.h>
|
||||
|
||||
|
||||
+22
-37
@@ -1154,7 +1154,7 @@ static int mpls_netconf_fill_devconf(struct sk_buff *skb, struct mpls_dev *mdev,
|
||||
|
||||
if ((all || type == NETCONFA_INPUT) &&
|
||||
nla_put_s32(skb, NETCONFA_INPUT,
|
||||
mdev->input_enabled) < 0)
|
||||
READ_ONCE(mdev->input_enabled)) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
@@ -1303,11 +1303,12 @@ static int mpls_netconf_dump_devconf(struct sk_buff *skb,
|
||||
{
|
||||
const struct nlmsghdr *nlh = cb->nlh;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct hlist_head *head;
|
||||
struct {
|
||||
unsigned long ifindex;
|
||||
} *ctx = (void *)cb->ctx;
|
||||
struct net_device *dev;
|
||||
struct mpls_dev *mdev;
|
||||
int idx, s_idx;
|
||||
int h, s_h;
|
||||
int err = 0;
|
||||
|
||||
if (cb->strict_check) {
|
||||
struct netlink_ext_ack *extack = cb->extack;
|
||||
@@ -1324,40 +1325,23 @@ static int mpls_netconf_dump_devconf(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
s_h = cb->args[0];
|
||||
s_idx = idx = cb->args[1];
|
||||
|
||||
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
|
||||
idx = 0;
|
||||
head = &net->dev_index_head[h];
|
||||
rcu_read_lock();
|
||||
cb->seq = net->dev_base_seq;
|
||||
hlist_for_each_entry_rcu(dev, head, index_hlist) {
|
||||
if (idx < s_idx)
|
||||
goto cont;
|
||||
mdev = mpls_dev_get(dev);
|
||||
if (!mdev)
|
||||
goto cont;
|
||||
if (mpls_netconf_fill_devconf(skb, mdev,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
nlh->nlmsg_seq,
|
||||
RTM_NEWNETCONF,
|
||||
NLM_F_MULTI,
|
||||
NETCONFA_ALL) < 0) {
|
||||
rcu_read_unlock();
|
||||
goto done;
|
||||
}
|
||||
nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
||||
cont:
|
||||
idx++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
rcu_read_lock();
|
||||
for_each_netdev_dump(net, dev, ctx->ifindex) {
|
||||
mdev = mpls_dev_get(dev);
|
||||
if (!mdev)
|
||||
continue;
|
||||
err = mpls_netconf_fill_devconf(skb, mdev,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
nlh->nlmsg_seq,
|
||||
RTM_NEWNETCONF,
|
||||
NLM_F_MULTI,
|
||||
NETCONFA_ALL);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
done:
|
||||
cb->args[0] = h;
|
||||
cb->args[1] = idx;
|
||||
rcu_read_unlock();
|
||||
|
||||
return skb->len;
|
||||
return err;
|
||||
}
|
||||
|
||||
#define MPLS_PERDEV_SYSCTL_OFFSET(field) \
|
||||
@@ -2773,7 +2757,8 @@ static int __init mpls_init(void)
|
||||
mpls_getroute, mpls_dump_routes, 0);
|
||||
rtnl_register_module(THIS_MODULE, PF_MPLS, RTM_GETNETCONF,
|
||||
mpls_netconf_get_devconf,
|
||||
mpls_netconf_dump_devconf, 0);
|
||||
mpls_netconf_dump_devconf,
|
||||
RTNL_FLAG_DUMP_UNLOCKED);
|
||||
err = ipgre_tunnel_encap_add_mpls_ops();
|
||||
if (err)
|
||||
pr_err("Can't add mpls over gre tunnel ops\n");
|
||||
|
||||
@@ -1068,6 +1068,7 @@ static void ack_update_msk(struct mptcp_sock *msk,
|
||||
__mptcp_snd_una_update(msk, new_snd_una);
|
||||
__mptcp_data_acked(sk);
|
||||
}
|
||||
msk->last_ack_recv = tcp_jiffies32;
|
||||
mptcp_data_unlock(sk);
|
||||
|
||||
trace_ack_update_msk(mp_opt->data_ack,
|
||||
|
||||
@@ -706,6 +706,8 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
|
||||
}
|
||||
} while (more_data_avail);
|
||||
|
||||
if (moved > 0)
|
||||
msk->last_data_recv = tcp_jiffies32;
|
||||
*bytes += moved;
|
||||
return done;
|
||||
}
|
||||
@@ -1556,6 +1558,8 @@ static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
|
||||
err = copied;
|
||||
|
||||
out:
|
||||
if (err > 0)
|
||||
msk->last_data_sent = tcp_jiffies32;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2793,6 +2797,9 @@ static void __mptcp_init_sock(struct sock *sk)
|
||||
WRITE_ONCE(msk->allow_infinite_fallback, true);
|
||||
msk->recovery = false;
|
||||
msk->subflow_id = 1;
|
||||
msk->last_data_sent = tcp_jiffies32;
|
||||
msk->last_data_recv = tcp_jiffies32;
|
||||
msk->last_ack_recv = tcp_jiffies32;
|
||||
|
||||
mptcp_pm_data_init(msk);
|
||||
|
||||
|
||||
@@ -282,6 +282,9 @@ struct mptcp_sock {
|
||||
u64 bytes_acked;
|
||||
u64 snd_una;
|
||||
u64 wnd_end;
|
||||
u32 last_data_sent;
|
||||
u32 last_data_recv;
|
||||
u32 last_ack_recv;
|
||||
unsigned long timer_ival;
|
||||
u32 token;
|
||||
int rmem_released;
|
||||
|
||||
+11
-5
@@ -898,6 +898,7 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
u32 flags = 0;
|
||||
bool slow;
|
||||
u32 now;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
@@ -926,11 +927,6 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
|
||||
if (READ_ONCE(msk->can_ack))
|
||||
flags |= MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED;
|
||||
info->mptcpi_flags = flags;
|
||||
mptcp_data_lock(sk);
|
||||
info->mptcpi_snd_una = msk->snd_una;
|
||||
info->mptcpi_rcv_nxt = msk->ack_seq;
|
||||
info->mptcpi_bytes_acked = msk->bytes_acked;
|
||||
mptcp_data_unlock(sk);
|
||||
|
||||
slow = lock_sock_fast(sk);
|
||||
info->mptcpi_csum_enabled = READ_ONCE(msk->csum_enabled);
|
||||
@@ -942,7 +938,17 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
|
||||
info->mptcpi_bytes_retrans = msk->bytes_retrans;
|
||||
info->mptcpi_subflows_total = info->mptcpi_subflows +
|
||||
__mptcp_has_initial_subflow(msk);
|
||||
now = tcp_jiffies32;
|
||||
info->mptcpi_last_data_sent = jiffies_to_msecs(now - msk->last_data_sent);
|
||||
info->mptcpi_last_data_recv = jiffies_to_msecs(now - msk->last_data_recv);
|
||||
unlock_sock_fast(sk, slow);
|
||||
|
||||
mptcp_data_lock(sk);
|
||||
info->mptcpi_last_ack_recv = jiffies_to_msecs(now - msk->last_ack_recv);
|
||||
info->mptcpi_snd_una = msk->snd_una;
|
||||
info->mptcpi_rcv_nxt = msk->ack_seq;
|
||||
info->mptcpi_bytes_acked = msk->bytes_acked;
|
||||
mptcp_data_unlock(sk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mptcp_diag_fill_info);
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <net/inet_connection_sock.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/tls.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include "tls.h"
|
||||
#include "trace.h"
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <crypto/aead.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <net/ip6_checksum.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
|
||||
#include "tls.h"
|
||||
|
||||
@@ -277,7 +278,7 @@ static int fill_sg_in(struct scatterlist *sg_in,
|
||||
for (i = 0; remaining > 0; i++) {
|
||||
skb_frag_t *frag = &record->frags[i];
|
||||
|
||||
__skb_frag_ref(frag);
|
||||
__skb_frag_ref(frag, false);
|
||||
sg_set_page(sg_in + i, skb_frag_page(frag),
|
||||
skb_frag_size(frag), skb_frag_off(frag));
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/* Copyright (c) 2016 Tom Herbert <tom@herbertland.com> */
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/skbuff_ref.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <net/strparser.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
@@ -2147,7 +2147,6 @@ recv_end:
|
||||
if (ret) {
|
||||
if (err >= 0 || err == -EINPROGRESS)
|
||||
err = ret;
|
||||
decrypted = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
@@ -200,6 +200,58 @@ chk_msk_cestab()
|
||||
"${expected}" "${msg}" ""
|
||||
}
|
||||
|
||||
msk_info_get_value()
|
||||
{
|
||||
local port="${1}"
|
||||
local info="${2}"
|
||||
|
||||
ss -N "${ns}" -inHM dport "${port}" | \
|
||||
mptcp_lib_get_info_value "${info}" "${info}"
|
||||
}
|
||||
|
||||
chk_msk_info()
|
||||
{
|
||||
local port="${1}"
|
||||
local info="${2}"
|
||||
local cnt="${3}"
|
||||
local msg="....chk ${info}"
|
||||
local delta_ms=250 # half what we waited before, just to be sure
|
||||
local now
|
||||
|
||||
now=$(msk_info_get_value "${port}" "${info}")
|
||||
|
||||
mptcp_lib_print_title "${msg}"
|
||||
if { [ -z "${cnt}" ] || [ -z "${now}" ]; } &&
|
||||
! mptcp_lib_expect_all_features; then
|
||||
mptcp_lib_pr_skip "Feature probably not supported"
|
||||
mptcp_lib_result_skip "${msg}"
|
||||
elif [ "$((cnt + delta_ms))" -lt "${now}" ]; then
|
||||
mptcp_lib_pr_ok
|
||||
mptcp_lib_result_pass "${msg}"
|
||||
else
|
||||
mptcp_lib_pr_fail "value of ${info} changed by $((now - cnt))ms," \
|
||||
"expected at least ${delta_ms}ms"
|
||||
mptcp_lib_result_fail "${msg}"
|
||||
ret=${KSFT_FAIL}
|
||||
fi
|
||||
}
|
||||
|
||||
chk_last_time_info()
|
||||
{
|
||||
local port="${1}"
|
||||
local data_sent data_recv ack_recv
|
||||
|
||||
data_sent=$(msk_info_get_value "${port}" "last_data_sent")
|
||||
data_recv=$(msk_info_get_value "${port}" "last_data_recv")
|
||||
ack_recv=$(msk_info_get_value "${port}" "last_ack_recv")
|
||||
|
||||
sleep 0.5 # wait to check after if the timestamps difference
|
||||
|
||||
chk_msk_info "${port}" "last_data_sent" "${data_sent}"
|
||||
chk_msk_info "${port}" "last_data_recv" "${data_recv}"
|
||||
chk_msk_info "${port}" "last_ack_recv" "${ack_recv}"
|
||||
}
|
||||
|
||||
wait_connected()
|
||||
{
|
||||
local listener_ns="${1}"
|
||||
@@ -233,6 +285,7 @@ echo "b" | \
|
||||
127.0.0.1 >/dev/null &
|
||||
wait_connected $ns 10000
|
||||
chk_msk_nr 2 "after MPC handshake "
|
||||
chk_last_time_info 10000
|
||||
chk_msk_remote_key_nr 2 "....chk remote_key"
|
||||
chk_msk_fallback_nr 0 "....chk no fallback"
|
||||
chk_msk_inuse 2
|
||||
|
||||
Reference in New Issue
Block a user