Merge 267e31750a ("Merge branch 'phy-listing-link_topology-tracking'") into android-mainline
Steps on the way to 6.10-rc1 Resolves merge conflicts in: include/trace/events/rpcgss.h net/core/dev.c Change-Id: I5583f92563983ee27432e07e1bc7fb194a6a45fc Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -158,7 +158,7 @@ properties:
|
||||
type: &attr-type
|
||||
enum: [ unused, pad, flag, binary,
|
||||
uint, sint, u8, u16, u32, u64, s32, s64,
|
||||
string, nest, array-nest, nest-type-value ]
|
||||
string, nest, indexed-array, nest-type-value ]
|
||||
doc:
|
||||
description: Documentation of the attribute.
|
||||
type: string
|
||||
|
||||
@@ -201,7 +201,7 @@ properties:
|
||||
description: The netlink attribute type
|
||||
enum: [ unused, pad, flag, binary, bitfield32,
|
||||
uint, sint, u8, u16, u32, u64, s32, s64,
|
||||
string, nest, array-nest, nest-type-value ]
|
||||
string, nest, indexed-array, nest-type-value ]
|
||||
doc:
|
||||
description: Documentation of the attribute.
|
||||
type: string
|
||||
|
||||
@@ -124,7 +124,7 @@ properties:
|
||||
type: &attr-type
|
||||
enum: [ unused, pad, flag, binary,
|
||||
uint, sint, u8, u16, u32, u64, s32, s64,
|
||||
string, nest, array-nest, nest-type-value ]
|
||||
string, nest, indexed-array, nest-type-value ]
|
||||
doc:
|
||||
description: Documentation of the attribute.
|
||||
type: string
|
||||
|
||||
@@ -222,7 +222,7 @@ properties:
|
||||
description: The netlink attribute type
|
||||
enum: [ unused, pad, flag, binary, bitfield32,
|
||||
u8, u16, u32, u64, s8, s16, s32, s64,
|
||||
string, nest, array-nest, nest-type-value,
|
||||
string, nest, indexed-array, nest-type-value,
|
||||
sub-message ]
|
||||
doc:
|
||||
description: Documentation of the attribute.
|
||||
|
||||
@@ -18,7 +18,6 @@ definitions:
|
||||
entries: []
|
||||
-
|
||||
name: header-flags
|
||||
enum-name:
|
||||
type: flags
|
||||
entries: [ compact-bitsets, omit-reply, stats ]
|
||||
|
||||
@@ -565,6 +564,18 @@ attribute-sets:
|
||||
-
|
||||
name: tx-lpi-timer
|
||||
type: u32
|
||||
-
|
||||
name: ts-stat
|
||||
attributes:
|
||||
-
|
||||
name: tx-pkts
|
||||
type: uint
|
||||
-
|
||||
name: tx-lost
|
||||
type: uint
|
||||
-
|
||||
name: tx-err
|
||||
type: uint
|
||||
-
|
||||
name: tsinfo
|
||||
attributes:
|
||||
@@ -587,6 +598,10 @@ attribute-sets:
|
||||
-
|
||||
name: phc-index
|
||||
type: u32
|
||||
-
|
||||
name: stats
|
||||
type: nest
|
||||
nested-attributes: ts-stat
|
||||
-
|
||||
name: cable-result
|
||||
attributes:
|
||||
@@ -1394,6 +1409,7 @@ operations:
|
||||
- tx-types
|
||||
- rx-filters
|
||||
- phc-index
|
||||
- stats
|
||||
dump: *tsinfo-get-op
|
||||
-
|
||||
name: cable-test-act
|
||||
|
||||
@@ -65,11 +65,13 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: ops
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: op-attrs
|
||||
-
|
||||
name: mcast-groups
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: mcast-group-attrs
|
||||
-
|
||||
name: policy
|
||||
|
||||
@@ -1696,7 +1696,8 @@ attribute-sets:
|
||||
type: binary
|
||||
-
|
||||
name: hw-s-info
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: hw-s-info-one
|
||||
-
|
||||
name: l3-stats
|
||||
|
||||
@@ -1988,7 +1988,8 @@ attribute-sets:
|
||||
nested-attributes: tc-ematch-attrs
|
||||
-
|
||||
name: act
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: police
|
||||
@@ -2128,7 +2129,8 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: tin-stats
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-cake-tin-stats-attrs
|
||||
-
|
||||
name: deficit
|
||||
@@ -2348,7 +2350,8 @@ attribute-sets:
|
||||
type: string
|
||||
-
|
||||
name: act
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: key-eth-dst
|
||||
@@ -2849,7 +2852,8 @@ attribute-sets:
|
||||
type: string
|
||||
-
|
||||
name: act
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: mask
|
||||
@@ -3002,7 +3006,8 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: act
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: flags
|
||||
@@ -3375,7 +3380,8 @@ attribute-sets:
|
||||
nested-attributes: tc-police-attrs
|
||||
-
|
||||
name: act
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: tc-taprio-attrs
|
||||
@@ -3593,7 +3599,8 @@ attribute-sets:
|
||||
nested-attributes: tc-police-attrs
|
||||
-
|
||||
name: act
|
||||
type: array-nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: indev
|
||||
|
||||
@@ -300,6 +300,11 @@ the software port.
|
||||
in the beginning of the queue. This is a normal condition.
|
||||
- Informative
|
||||
|
||||
* - `tx[i]_timestamps`
|
||||
- Transmitted packets that were hardware timestamped at the device's DMA
|
||||
layer.
|
||||
- Informative
|
||||
|
||||
* - `tx[i]_added_vlan_packets`
|
||||
- The number of packets sent where vlan tag insertion was offloaded to the
|
||||
hardware.
|
||||
@@ -702,6 +707,12 @@ the software port.
|
||||
the device typically ensures not posting the CQE.
|
||||
- Error
|
||||
|
||||
* - `ptp_cq[i]_lost_cqe`
|
||||
- Number of times a CQE is expected to not be delivered on the PTP
|
||||
timestamping CQE by the device due to a time delta elapsing. If such a
|
||||
CQE is somehow delivered, `ptp_cq[i]_late_cqe` is incremented.
|
||||
- Error
|
||||
|
||||
.. [#ring_global] The corresponding ring and global counters do not share the
|
||||
same name (i.e. do not follow the common naming scheme).
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ Structure of this header is
|
||||
``ETHTOOL_A_HEADER_DEV_INDEX`` u32 device ifindex
|
||||
``ETHTOOL_A_HEADER_DEV_NAME`` string device name
|
||||
``ETHTOOL_A_HEADER_FLAGS`` u32 flags common for all requests
|
||||
``ETHTOOL_A_HEADER_PHY_INDEX`` u32 phy device index
|
||||
============================== ====== =============================
|
||||
|
||||
``ETHTOOL_A_HEADER_DEV_INDEX`` and ``ETHTOOL_A_HEADER_DEV_NAME`` identify the
|
||||
@@ -81,6 +82,12 @@ the behaviour is backward compatible, i.e. requests from old clients not aware
|
||||
of the flag should be interpreted the way the client expects. A client must
|
||||
not set flags it does not understand.
|
||||
|
||||
``ETHTOOL_A_HEADER_PHY_INDEX`` identifies the Ethernet PHY the message relates to.
|
||||
As there are numerous commands that are related to PHY configuration, and because
|
||||
there may be more than one PHY on the link, the PHY index can be passed in the
|
||||
request for the commands that needs it. It is, however, not mandatory, and if it
|
||||
is not passed for commands that target a PHY, the net_device.phydev pointer
|
||||
is used.
|
||||
|
||||
Bit sets
|
||||
========
|
||||
@@ -1237,12 +1244,21 @@ Kernel response contents:
|
||||
``ETHTOOL_A_TSINFO_TX_TYPES`` bitset supported Tx types
|
||||
``ETHTOOL_A_TSINFO_RX_FILTERS`` bitset supported Rx filters
|
||||
``ETHTOOL_A_TSINFO_PHC_INDEX`` u32 PTP hw clock index
|
||||
``ETHTOOL_A_TSINFO_STATS`` nested HW timestamping statistics
|
||||
===================================== ====== ==========================
|
||||
|
||||
``ETHTOOL_A_TSINFO_PHC_INDEX`` is absent if there is no associated PHC (there
|
||||
is no special value for this case). The bitset attributes are omitted if they
|
||||
would be empty (no bit set).
|
||||
|
||||
Additional hardware timestamping statistics response contents:
|
||||
|
||||
===================================== ====== ===================================
|
||||
``ETHTOOL_A_TS_STAT_TX_PKTS`` u64 Packets with Tx HW timestamps
|
||||
``ETHTOOL_A_TS_STAT_TX_LOST`` u64 Tx HW timestamp not arrived count
|
||||
``ETHTOOL_A_TS_STAT_TX_ERR`` u64 HW error request Tx timestamp count
|
||||
===================================== ====== ===================================
|
||||
|
||||
CABLE_TEST
|
||||
==========
|
||||
|
||||
|
||||
@@ -46,10 +46,16 @@ For reference the ``multi-attr`` array may look like this::
|
||||
|
||||
where ``ARRAY-ATTR`` is the array entry type.
|
||||
|
||||
array-nest
|
||||
~~~~~~~~~~
|
||||
indexed-array
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
``array-nest`` creates the following structure::
|
||||
``indexed-array`` wraps the entire array in an extra attribute (hence
|
||||
limiting its size to 64kB). The ``ENTRY`` nests are special and have the
|
||||
index of the entry as their type instead of normal attribute type.
|
||||
|
||||
A ``sub-type`` is needed to describe what type in the ``ENTRY``. A ``nest``
|
||||
``sub-type`` means there are nest arrays in the ``ENTRY``, with the structure
|
||||
looks like::
|
||||
|
||||
[SOME-OTHER-ATTR]
|
||||
[ARRAY-ATTR]
|
||||
@@ -60,9 +66,13 @@ array-nest
|
||||
[MEMBER1]
|
||||
[MEMBER2]
|
||||
|
||||
It wraps the entire array in an extra attribute (hence limiting its size
|
||||
to 64kB). The ``ENTRY`` nests are special and have the index of the entry
|
||||
as their type instead of normal attribute type.
|
||||
Other ``sub-type`` like ``u32`` means there is only one member as described
|
||||
in ``sub-type`` in the ``ENTRY``. The structure looks like::
|
||||
|
||||
[SOME-OTHER-ATTR]
|
||||
[ARRAY-ATTR]
|
||||
[ENTRY u32]
|
||||
[ENTRY u32]
|
||||
|
||||
type-value
|
||||
~~~~~~~~~~
|
||||
|
||||
@@ -8062,6 +8062,8 @@ F: include/linux/mii.h
|
||||
F: include/linux/of_net.h
|
||||
F: include/linux/phy.h
|
||||
F: include/linux/phy_fixed.h
|
||||
F: include/linux/phy_link_topology.h
|
||||
F: include/linux/phy_link_topology_core.h
|
||||
F: include/linux/phylib_stubs.h
|
||||
F: include/linux/platform_data/mdio-bcm-unimac.h
|
||||
F: include/linux/platform_data/mdio-gpio.h
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
# Makefile for the CAPI subsystem used by BT_CMTP
|
||||
|
||||
obj-$(CONFIG_BT_CMTP) += kernelcapi.o
|
||||
kernelcapi-y := kcapi.o capiutil.o capi.o kcapi_proc.o
|
||||
kernelcapi-y := kcapi.o capiutil.o capi.o
|
||||
kernelcapi-$(CONFIG_PROC_FS) += kcapi_proc.o
|
||||
|
||||
@@ -917,13 +917,16 @@ int __init kcapi_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
kcapi_proc_init();
|
||||
if (IS_ENABLED(CONFIG_PROC_FS))
|
||||
kcapi_proc_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kcapi_exit(void)
|
||||
{
|
||||
kcapi_proc_exit();
|
||||
if (IS_ENABLED(CONFIG_PROC_FS))
|
||||
kcapi_proc_exit();
|
||||
|
||||
cdebug_exit();
|
||||
destroy_workqueue(kcapi_wq);
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
Setting to > 1512 effectively disables this feature. */
|
||||
static int rx_copybreak = 200;
|
||||
|
||||
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
|
||||
static const int mtu = 1500;
|
||||
|
||||
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
|
||||
static int max_interrupt_work = 20;
|
||||
|
||||
|
||||
@@ -538,7 +538,6 @@ static const struct xgbe_version_data xgbe_v1 = {
|
||||
.tx_tstamp_workaround = 1,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id xgbe_acpi_match[] = {
|
||||
{ .id = "AMDI8001",
|
||||
.driver_data = (kernel_ulong_t)&xgbe_v1 },
|
||||
@@ -546,9 +545,7 @@ static const struct acpi_device_id xgbe_acpi_match[] = {
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id xgbe_of_match[] = {
|
||||
{ .compatible = "amd,xgbe-seattle-v1a",
|
||||
.data = &xgbe_v1 },
|
||||
@@ -556,7 +553,6 @@ static const struct of_device_id xgbe_of_match[] = {
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, xgbe_of_match);
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(xgbe_platform_pm_ops,
|
||||
xgbe_platform_suspend, xgbe_platform_resume);
|
||||
@@ -564,12 +560,8 @@ static SIMPLE_DEV_PM_OPS(xgbe_platform_pm_ops,
|
||||
static struct platform_driver xgbe_driver = {
|
||||
.driver = {
|
||||
.name = XGBE_DRV_NAME,
|
||||
#ifdef CONFIG_ACPI
|
||||
.acpi_match_table = xgbe_acpi_match,
|
||||
#endif
|
||||
#ifdef CONFIG_OF
|
||||
.of_match_table = xgbe_of_match,
|
||||
#endif
|
||||
.pm = &xgbe_platform_pm_ops,
|
||||
},
|
||||
.probe = xgbe_platform_probe,
|
||||
|
||||
@@ -131,7 +131,7 @@ static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts,
|
||||
if (!tmo_us)
|
||||
tmo_us = BNXT_PTP_QTS_TIMEOUT;
|
||||
tmo_us = min(tmo_us, BNXT_PTP_QTS_MAX_TMO_US);
|
||||
req->ts_req_timeout = cpu_to_le16(txts_tmo);
|
||||
req->ts_req_timeout = cpu_to_le16(tmo_us);
|
||||
}
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
|
||||
|
||||
@@ -1143,7 +1143,6 @@ void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq);
|
||||
int mlx5e_create_tis(struct mlx5_core_dev *mdev, void *in, u32 *tisn);
|
||||
void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn);
|
||||
|
||||
int mlx5e_update_nic_rx(struct mlx5e_priv *priv);
|
||||
void mlx5e_update_carrier(struct mlx5e_priv *priv);
|
||||
int mlx5e_close(struct net_device *netdev);
|
||||
int mlx5e_open(struct net_device *netdev);
|
||||
@@ -1180,23 +1179,12 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
|
||||
struct ethtool_coalesce *coal,
|
||||
struct kernel_ethtool_coalesce *kernel_coal,
|
||||
struct netlink_ext_ack *extack);
|
||||
int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
|
||||
struct ethtool_link_ksettings *link_ksettings);
|
||||
int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
|
||||
const struct ethtool_link_ksettings *link_ksettings);
|
||||
int mlx5e_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh);
|
||||
int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack);
|
||||
u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv);
|
||||
u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv);
|
||||
int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
|
||||
struct ethtool_ts_info *info);
|
||||
int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
|
||||
struct ethtool_flash *flash);
|
||||
void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam);
|
||||
int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam);
|
||||
|
||||
/* mlx5e generic netdev management API */
|
||||
static inline bool
|
||||
|
||||
@@ -292,10 +292,15 @@ enum mlx5e_fec_supported_link_mode {
|
||||
MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X,
|
||||
MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X,
|
||||
MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X,
|
||||
MLX5E_FEC_SUPPORTED_LINK_MODE_100G_1X,
|
||||
MLX5E_FEC_SUPPORTED_LINK_MODE_200G_2X,
|
||||
MLX5E_FEC_SUPPORTED_LINK_MODE_400G_4X,
|
||||
MLX5E_FEC_SUPPORTED_LINK_MODE_800G_8X,
|
||||
MLX5E_MAX_FEC_SUPPORTED_LINK_MODE,
|
||||
};
|
||||
|
||||
#define MLX5E_FEC_FIRST_50G_PER_LANE_MODE MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X
|
||||
#define MLX5E_FEC_FIRST_100G_PER_LANE_MODE MLX5E_FEC_SUPPORTED_LINK_MODE_100G_1X
|
||||
|
||||
#define MLX5E_FEC_OVERRIDE_ADMIN_POLICY(buf, policy, write, link) \
|
||||
do { \
|
||||
@@ -308,6 +313,17 @@ enum mlx5e_fec_supported_link_mode {
|
||||
*_policy = MLX5_GET(pplm_reg, _buf, fec_override_admin_##link); \
|
||||
} while (0)
|
||||
|
||||
/* Returns true if FEC can be set for a given link mode. */
|
||||
static bool mlx5e_is_fec_supported_link_mode(struct mlx5_core_dev *dev,
|
||||
enum mlx5e_fec_supported_link_mode link_mode)
|
||||
{
|
||||
return link_mode < MLX5E_FEC_FIRST_50G_PER_LANE_MODE ||
|
||||
(link_mode < MLX5E_FEC_FIRST_100G_PER_LANE_MODE &&
|
||||
MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm)) ||
|
||||
(link_mode >= MLX5E_FEC_FIRST_100G_PER_LANE_MODE &&
|
||||
MLX5_CAP_PCAM_FEATURE(dev, fec_100G_per_lane_in_pplm));
|
||||
}
|
||||
|
||||
/* get/set FEC admin field for a given speed */
|
||||
static int mlx5e_fec_admin_field(u32 *pplm, u16 *fec_policy, bool write,
|
||||
enum mlx5e_fec_supported_link_mode link_mode)
|
||||
@@ -340,6 +356,18 @@ static int mlx5e_fec_admin_field(u32 *pplm, u16 *fec_policy, bool write,
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X:
|
||||
MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 400g_8x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_1X:
|
||||
MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g_1x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_2X:
|
||||
MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 200g_2x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_4X:
|
||||
MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 400g_4x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_800G_8X:
|
||||
MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 800g_8x);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -381,6 +409,18 @@ static int mlx5e_get_fec_cap_field(u32 *pplm, u16 *fec_cap,
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X:
|
||||
*fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 400g_8x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_1X:
|
||||
*fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 100g_1x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_2X:
|
||||
*fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 200g_2x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_4X:
|
||||
*fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 400g_4x);
|
||||
break;
|
||||
case MLX5E_FEC_SUPPORTED_LINK_MODE_800G_8X:
|
||||
*fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 800g_8x);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -389,7 +429,6 @@ static int mlx5e_get_fec_cap_field(u32 *pplm, u16 *fec_cap,
|
||||
|
||||
bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
|
||||
{
|
||||
bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
|
||||
u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
|
||||
u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
|
||||
int sz = MLX5_ST_SZ_BYTES(pplm_reg);
|
||||
@@ -407,7 +446,7 @@ bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
|
||||
for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
|
||||
u16 fec_caps;
|
||||
|
||||
if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
|
||||
if (!mlx5e_is_fec_supported_link_mode(dev, i))
|
||||
break;
|
||||
|
||||
mlx5e_get_fec_cap_field(out, &fec_caps, i);
|
||||
@@ -420,7 +459,6 @@ bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
|
||||
int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
|
||||
u16 *fec_configured_mode)
|
||||
{
|
||||
bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
|
||||
u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
|
||||
u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
|
||||
int sz = MLX5_ST_SZ_BYTES(pplm_reg);
|
||||
@@ -445,7 +483,7 @@ int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
|
||||
|
||||
*fec_configured_mode = 0;
|
||||
for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
|
||||
if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
|
||||
if (!mlx5e_is_fec_supported_link_mode(dev, i))
|
||||
break;
|
||||
|
||||
mlx5e_fec_admin_field(out, fec_configured_mode, 0, i);
|
||||
@@ -489,13 +527,13 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
|
||||
u16 conf_fec = fec_policy;
|
||||
u16 fec_caps = 0;
|
||||
|
||||
if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
|
||||
if (!mlx5e_is_fec_supported_link_mode(dev, i))
|
||||
break;
|
||||
|
||||
/* RS fec in ethtool is mapped to MLX5E_FEC_RS_528_514
|
||||
* to link modes up to 25G per lane and to
|
||||
* MLX5E_FEC_RS_544_514 in the new link modes based on
|
||||
* 50 G per lane
|
||||
* 50G or 100G per lane
|
||||
*/
|
||||
if (conf_fec == (1 << MLX5E_FEC_RS_528_514) &&
|
||||
i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE)
|
||||
|
||||
@@ -169,6 +169,7 @@ static void mlx5e_ptpsq_mark_ts_cqes_undelivered(struct mlx5e_ptpsq *ptpsq,
|
||||
WARN_ON_ONCE(!pos->inuse);
|
||||
pos->inuse = false;
|
||||
list_del(&pos->entry);
|
||||
ptpsq->cq_stats->lost_cqe++;
|
||||
}
|
||||
spin_unlock_bh(&cqe_list->tracker_list_lock);
|
||||
}
|
||||
|
||||
@@ -1024,8 +1024,8 @@ static void get_lp_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_lp,
|
||||
ptys2ethtool_adver_link(lp_advertising, eth_proto_lp, ext);
|
||||
}
|
||||
|
||||
int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
static int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {};
|
||||
@@ -1195,8 +1195,8 @@ static bool ext_requested(u8 autoneg, const unsigned long *adver, bool ext_suppo
|
||||
return autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_supported;
|
||||
}
|
||||
|
||||
int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
|
||||
const struct ethtool_link_ksettings *link_ksettings)
|
||||
static int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
|
||||
const struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
struct mlx5_port_eth_proto eproto;
|
||||
@@ -1296,7 +1296,7 @@ static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
|
||||
return mlx5e_ethtool_get_rxfh_indir_size(priv);
|
||||
}
|
||||
|
||||
int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
|
||||
static int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
u32 rss_context = rxfh->rss_context;
|
||||
@@ -1309,8 +1309,8 @@ int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack)
|
||||
static int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
u32 *rss_context = &rxfh->rss_context;
|
||||
@@ -1452,8 +1452,8 @@ static void mlx5e_get_pause_stats(struct net_device *netdev,
|
||||
mlx5e_stats_pause_get(priv, pause_stats);
|
||||
}
|
||||
|
||||
void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
static void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int err;
|
||||
@@ -1474,8 +1474,8 @@ static void mlx5e_get_pauseparam(struct net_device *netdev,
|
||||
mlx5e_ethtool_get_pauseparam(priv, pauseparam);
|
||||
}
|
||||
|
||||
int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
static int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int err;
|
||||
@@ -2428,6 +2428,14 @@ static void mlx5e_get_rmon_stats(struct net_device *netdev,
|
||||
mlx5e_stats_rmon_get(priv, rmon_stats, ranges);
|
||||
}
|
||||
|
||||
static void mlx5e_get_ts_stats(struct net_device *netdev,
|
||||
struct ethtool_ts_stats *ts_stats)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
||||
mlx5e_stats_ts_get(priv, ts_stats);
|
||||
}
|
||||
|
||||
const struct ethtool_ops mlx5e_ethtool_ops = {
|
||||
.cap_rss_ctx_supported = true,
|
||||
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
|
||||
@@ -2477,5 +2485,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
|
||||
.get_eth_mac_stats = mlx5e_get_eth_mac_stats,
|
||||
.get_eth_ctrl_stats = mlx5e_get_eth_ctrl_stats,
|
||||
.get_rmon_stats = mlx5e_get_rmon_stats,
|
||||
.get_ts_stats = mlx5e_get_ts_stats,
|
||||
.get_link_ext_stats = mlx5e_get_link_ext_stats
|
||||
};
|
||||
|
||||
@@ -5562,7 +5562,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
|
||||
mlx5e_ipsec_cleanup(priv);
|
||||
}
|
||||
|
||||
int mlx5e_update_nic_rx(struct mlx5e_priv *priv)
|
||||
static int mlx5e_update_nic_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
return mlx5e_refresh_tirs(priv, false, false);
|
||||
}
|
||||
|
||||
@@ -1172,6 +1172,51 @@ void mlx5e_stats_rmon_get(struct mlx5e_priv *priv,
|
||||
*ranges = mlx5e_rmon_ranges;
|
||||
}
|
||||
|
||||
void mlx5e_stats_ts_get(struct mlx5e_priv *priv,
|
||||
struct ethtool_ts_stats *ts_stats)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
|
||||
if (priv->tx_ptp_opened) {
|
||||
struct mlx5e_ptp *ptp = priv->channels.ptp;
|
||||
|
||||
ts_stats->pkts = 0;
|
||||
ts_stats->err = 0;
|
||||
ts_stats->lost = 0;
|
||||
|
||||
/* Aggregate stats across all TCs */
|
||||
for (i = 0; i < ptp->num_tc; i++) {
|
||||
struct mlx5e_ptp_cq_stats *stats =
|
||||
ptp->ptpsq[i].cq_stats;
|
||||
|
||||
ts_stats->pkts += stats->cqe;
|
||||
ts_stats->err += stats->abort + stats->err_cqe +
|
||||
stats->late_cqe;
|
||||
ts_stats->lost += stats->lost_cqe;
|
||||
}
|
||||
} else {
|
||||
/* DMA layer will always successfully timestamp packets. Other
|
||||
* counters do not make sense for this layer.
|
||||
*/
|
||||
ts_stats->pkts = 0;
|
||||
|
||||
/* Aggregate stats across all SQs */
|
||||
for (j = 0; j < priv->channels.num; j++) {
|
||||
struct mlx5e_channel *c = priv->channels.c[j];
|
||||
|
||||
for (i = 0; i < c->num_tc; i++) {
|
||||
struct mlx5e_sq_stats *stats = c->sq[i].stats;
|
||||
|
||||
ts_stats->pkts += stats->timestamps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
}
|
||||
|
||||
#define PPORT_PHY_STATISTICAL_OFF(c) \
|
||||
MLX5_BYTE_OFF(ppcnt_reg, \
|
||||
counter_set.phys_layer_statistical_cntrs.c##_high)
|
||||
@@ -2066,6 +2111,7 @@ static const struct counter_desc sq_stats_desc[] = {
|
||||
{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_partial_inner) },
|
||||
{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, added_vlan_packets) },
|
||||
{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, nop) },
|
||||
{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, timestamps) },
|
||||
{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, mpwqe_blks) },
|
||||
{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, mpwqe_pkts) },
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
@@ -2178,6 +2224,7 @@ static const struct counter_desc ptp_cq_stats_desc[] = {
|
||||
{ MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, abort) },
|
||||
{ MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, abort_abs_diff_ns) },
|
||||
{ MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, late_cqe) },
|
||||
{ MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, lost_cqe) },
|
||||
};
|
||||
|
||||
static const struct counter_desc ptp_rq_stats_desc[] = {
|
||||
@@ -2217,6 +2264,7 @@ static const struct counter_desc qos_sq_stats_desc[] = {
|
||||
{ MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, csum_partial_inner) },
|
||||
{ MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, added_vlan_packets) },
|
||||
{ MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, nop) },
|
||||
{ MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, timestamps) },
|
||||
{ MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, mpwqe_blks) },
|
||||
{ MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, mpwqe_pkts) },
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
|
||||
@@ -128,6 +128,8 @@ void mlx5e_stats_eth_ctrl_get(struct mlx5e_priv *priv,
|
||||
void mlx5e_stats_rmon_get(struct mlx5e_priv *priv,
|
||||
struct ethtool_rmon_stats *rmon,
|
||||
const struct ethtool_rmon_hist_range **ranges);
|
||||
void mlx5e_stats_ts_get(struct mlx5e_priv *priv,
|
||||
struct ethtool_ts_stats *ts_stats);
|
||||
void mlx5e_get_link_ext_stats(struct net_device *dev,
|
||||
struct ethtool_link_ext_stats *stats);
|
||||
|
||||
@@ -431,6 +433,7 @@ struct mlx5e_sq_stats {
|
||||
u64 stopped;
|
||||
u64 dropped;
|
||||
u64 recover;
|
||||
u64 timestamps;
|
||||
/* dirtied @completion */
|
||||
u64 cqes ____cacheline_aligned_in_smp;
|
||||
u64 wake;
|
||||
@@ -463,6 +466,7 @@ struct mlx5e_ptp_cq_stats {
|
||||
u64 abort;
|
||||
u64 abort_abs_diff_ns;
|
||||
u64 late_cqe;
|
||||
u64 lost_cqe;
|
||||
};
|
||||
|
||||
struct mlx5e_rep_stats {
|
||||
|
||||
@@ -749,11 +749,13 @@ static void mlx5e_consume_skb(struct mlx5e_txqsq *sq, struct sk_buff *skb,
|
||||
u64 ts = get_cqe_ts(cqe);
|
||||
|
||||
hwts.hwtstamp = mlx5e_cqe_ts_to_ns(sq->ptp_cyc2time, sq->clock, ts);
|
||||
if (sq->ptpsq)
|
||||
if (sq->ptpsq) {
|
||||
mlx5e_skb_cb_hwtstamp_handler(skb, MLX5E_SKB_CB_CQE_HWTSTAMP,
|
||||
hwts.hwtstamp, sq->ptpsq->cq_stats);
|
||||
else
|
||||
} else {
|
||||
skb_tstamp_tx(skb, &hwts);
|
||||
sq->stats->timestamps++;
|
||||
}
|
||||
}
|
||||
|
||||
napi_consume_skb(skb, napi_budget);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Makefile for Linux PHY drivers
|
||||
|
||||
libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \
|
||||
linkmode.o
|
||||
linkmode.o phy_link_topology.o
|
||||
mdio-bus-y += mdio_bus.o mdio_device.o
|
||||
|
||||
ifdef CONFIG_MDIO_DEVICE
|
||||
|
||||
@@ -553,6 +553,8 @@ static const struct sfp_upstream_ops sfp_phy_ops = {
|
||||
.link_down = mv2222_sfp_link_down,
|
||||
.attach = phy_sfp_attach,
|
||||
.detach = phy_sfp_detach,
|
||||
.connect_phy = phy_sfp_connect_phy,
|
||||
.disconnect_phy = phy_sfp_disconnect_phy,
|
||||
};
|
||||
|
||||
static int mv2222_probe(struct phy_device *phydev)
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
|
||||
#define MII_VCT_TXPINS 0x1A
|
||||
#define MII_VCT_RXPINS 0x1B
|
||||
#define MII_VCT_SR 0x1C
|
||||
#define MII_VCT_TXPINS_ENVCT BIT(15)
|
||||
#define MII_VCT_TXRXPINS_VCTTST GENMASK(14, 13)
|
||||
#define MII_VCT_TXRXPINS_VCTTST_SHIFT 13
|
||||
@@ -2623,6 +2624,92 @@ static int m88e3082_vct_cable_test_get_status(struct phy_device *phydev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m88e1111_vct_cable_test_start(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = marvell_cable_test_start_common(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* It needs some magic workarounds described in VCT manual for this PHY.
|
||||
*/
|
||||
ret = phy_write(phydev, 29, 0x0018);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write(phydev, 30, 0x00c2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write(phydev, 30, 0x00ca);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write(phydev, 30, 0x00c2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write_paged(phydev, MII_MARVELL_COPPER_PAGE, MII_VCT_SR,
|
||||
MII_VCT_TXPINS_ENVCT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write(phydev, 29, 0x0018);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = phy_write(phydev, 30, 0x0042);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 m88e1111_vct_distrfln_2_cm(u8 distrfln)
|
||||
{
|
||||
if (distrfln < 36)
|
||||
return 0;
|
||||
|
||||
/* Original function for meters: y = 0.8018x - 28.751 */
|
||||
return (8018 * distrfln - 287510) / 100;
|
||||
}
|
||||
|
||||
static int m88e1111_vct_cable_test_get_status(struct phy_device *phydev,
|
||||
bool *finished)
|
||||
{
|
||||
u8 vcttst_res, distrfln;
|
||||
int ret, result;
|
||||
|
||||
*finished = false;
|
||||
|
||||
/* Each pair use one page: A-0, B-1, C-2, D-3 */
|
||||
for (u8 i = 0; i < 4; i++) {
|
||||
ret = phy_read_paged(phydev, i, MII_VCT_SR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (i == 0 && ret & MII_VCT_TXPINS_ENVCT)
|
||||
return 0;
|
||||
|
||||
distrfln = ret & MII_VCT_TXRXPINS_DISTRFLN;
|
||||
vcttst_res = (ret & MII_VCT_TXRXPINS_VCTTST) >>
|
||||
MII_VCT_TXRXPINS_VCTTST_SHIFT;
|
||||
|
||||
result = m88e3082_vct_cable_test_report_trans(vcttst_res,
|
||||
distrfln);
|
||||
ethnl_cable_test_result(phydev, i, result);
|
||||
|
||||
if (distrfln < MII_VCT_TXRXPINS_DISTRFLN_MAX) {
|
||||
u32 cm = m88e1111_vct_distrfln_2_cm(distrfln);
|
||||
|
||||
ethnl_cable_test_fault_length(phydev, i, cm);
|
||||
}
|
||||
}
|
||||
|
||||
*finished = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HWMON
|
||||
struct marvell_hwmon_ops {
|
||||
int (*config)(struct phy_device *phydev);
|
||||
@@ -3463,6 +3550,8 @@ static const struct sfp_upstream_ops m88e1510_sfp_ops = {
|
||||
.module_remove = m88e1510_sfp_remove,
|
||||
.attach = phy_sfp_attach,
|
||||
.detach = phy_sfp_detach,
|
||||
.connect_phy = phy_sfp_connect_phy,
|
||||
.disconnect_phy = phy_sfp_disconnect_phy,
|
||||
};
|
||||
|
||||
static int m88e1510_probe(struct phy_device *phydev)
|
||||
@@ -3534,6 +3623,7 @@ static struct phy_driver marvell_drivers[] = {
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1111",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
.probe = marvell_probe,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
@@ -3549,6 +3639,8 @@ static struct phy_driver marvell_drivers[] = {
|
||||
.get_stats = marvell_get_stats,
|
||||
.get_tunable = m88e1111_get_tunable,
|
||||
.set_tunable = m88e1111_set_tunable,
|
||||
.cable_test_start = m88e1111_vct_cable_test_start,
|
||||
.cable_test_get_status = m88e1111_vct_cable_test_get_status,
|
||||
},
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88E1111_FINISAR,
|
||||
@@ -3642,6 +3734,7 @@ static struct phy_driver marvell_drivers[] = {
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1145",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
.probe = marvell_probe,
|
||||
.config_init = m88e1145_config_init,
|
||||
.config_aneg = m88e1101_config_aneg,
|
||||
@@ -3656,6 +3749,8 @@ static struct phy_driver marvell_drivers[] = {
|
||||
.get_stats = marvell_get_stats,
|
||||
.get_tunable = m88e1111_get_tunable,
|
||||
.set_tunable = m88e1111_set_tunable,
|
||||
.cable_test_start = m88e1111_vct_cable_test_start,
|
||||
.cable_test_get_status = m88e1111_vct_cable_test_get_status,
|
||||
},
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88E1149R,
|
||||
|
||||
@@ -503,6 +503,8 @@ static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
static const struct sfp_upstream_ops mv3310_sfp_ops = {
|
||||
.attach = phy_sfp_attach,
|
||||
.detach = phy_sfp_detach,
|
||||
.connect_phy = phy_sfp_connect_phy,
|
||||
.disconnect_phy = phy_sfp_disconnect_phy,
|
||||
.module_insert = mv3310_sfp_insert,
|
||||
};
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/phylib_stubs.h>
|
||||
#include <linux/phy_led_triggers.h>
|
||||
#include <linux/phy_link_topology.h>
|
||||
#include <linux/pse-pd/pse.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
@@ -276,6 +277,14 @@ static void phy_mdio_device_remove(struct mdio_device *mdiodev)
|
||||
|
||||
static struct phy_driver genphy_driver;
|
||||
|
||||
static struct phy_link_topology *phy_get_link_topology(struct phy_device *phydev)
|
||||
{
|
||||
if (phydev->attached_dev)
|
||||
return phydev->attached_dev->link_topo;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LIST_HEAD(phy_fixup_list);
|
||||
static DEFINE_MUTEX(phy_fixup_lock);
|
||||
|
||||
@@ -1369,6 +1378,46 @@ phy_standalone_show(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR_RO(phy_standalone);
|
||||
|
||||
/**
|
||||
* phy_sfp_connect_phy - Connect the SFP module's PHY to the upstream PHY
|
||||
* @upstream: pointer to the upstream phy device
|
||||
* @phy: pointer to the SFP module's phy device
|
||||
*
|
||||
* This helper allows keeping track of PHY devices on the link. It adds the
|
||||
* SFP module's phy to the phy namespace of the upstream phy
|
||||
*/
|
||||
int phy_sfp_connect_phy(void *upstream, struct phy_device *phy)
|
||||
{
|
||||
struct phy_device *phydev = upstream;
|
||||
struct phy_link_topology *topo = phy_get_link_topology(phydev);
|
||||
|
||||
if (topo)
|
||||
return phy_link_topo_add_phy(topo, phy, PHY_UPSTREAM_PHY, phydev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(phy_sfp_connect_phy);
|
||||
|
||||
/**
|
||||
* phy_sfp_disconnect_phy - Disconnect the SFP module's PHY from the upstream PHY
|
||||
* @upstream: pointer to the upstream phy device
|
||||
* @phy: pointer to the SFP module's phy device
|
||||
*
|
||||
* This helper allows keeping track of PHY devices on the link. It removes the
|
||||
* SFP module's phy to the phy namespace of the upstream phy. As the module phy
|
||||
* will be destroyed, re-inserting the same module will add a new phy with a
|
||||
* new index.
|
||||
*/
|
||||
void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy)
|
||||
{
|
||||
struct phy_device *phydev = upstream;
|
||||
struct phy_link_topology *topo = phy_get_link_topology(phydev);
|
||||
|
||||
if (topo)
|
||||
phy_link_topo_del_phy(topo, phy);
|
||||
}
|
||||
EXPORT_SYMBOL(phy_sfp_disconnect_phy);
|
||||
|
||||
/**
|
||||
* phy_sfp_attach - attach the SFP bus to the PHY upstream network device
|
||||
* @upstream: pointer to the phy device
|
||||
@@ -1511,6 +1560,11 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
|
||||
if (phydev->sfp_bus_attached)
|
||||
dev->sfp_bus = phydev->sfp_bus;
|
||||
|
||||
err = phy_link_topo_add_phy(dev->link_topo, phydev,
|
||||
PHY_UPSTREAM_MAC, dev);
|
||||
if (err)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Some Ethernet drivers try to connect to a PHY device before
|
||||
@@ -1938,6 +1992,7 @@ void phy_detach(struct phy_device *phydev)
|
||||
if (dev) {
|
||||
phydev->attached_dev->phydev = NULL;
|
||||
phydev->attached_dev = NULL;
|
||||
phy_link_topo_del_phy(dev->link_topo, phydev);
|
||||
}
|
||||
phydev->phylink = NULL;
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Infrastructure to handle all PHY devices connected to a given netdev,
|
||||
* either directly or indirectly attached.
|
||||
*
|
||||
* Copyright (c) 2023 Maxime Chevallier<maxime.chevallier@bootlin.com>
|
||||
*/
|
||||
|
||||
#include <linux/phy_link_topology.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/xarray.h>
|
||||
|
||||
struct phy_link_topology *phy_link_topo_create(struct net_device *dev)
|
||||
{
|
||||
struct phy_link_topology *topo;
|
||||
|
||||
topo = kzalloc(sizeof(*topo), GFP_KERNEL);
|
||||
if (!topo)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
xa_init_flags(&topo->phys, XA_FLAGS_ALLOC1);
|
||||
topo->next_phy_index = 1;
|
||||
|
||||
return topo;
|
||||
}
|
||||
|
||||
void phy_link_topo_destroy(struct phy_link_topology *topo)
|
||||
{
|
||||
if (!topo)
|
||||
return;
|
||||
|
||||
xa_destroy(&topo->phys);
|
||||
kfree(topo);
|
||||
}
|
||||
|
||||
int phy_link_topo_add_phy(struct phy_link_topology *topo,
|
||||
struct phy_device *phy,
|
||||
enum phy_upstream upt, void *upstream)
|
||||
{
|
||||
struct phy_device_node *pdn;
|
||||
int ret;
|
||||
|
||||
pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
|
||||
if (!pdn)
|
||||
return -ENOMEM;
|
||||
|
||||
pdn->phy = phy;
|
||||
switch (upt) {
|
||||
case PHY_UPSTREAM_MAC:
|
||||
pdn->upstream.netdev = (struct net_device *)upstream;
|
||||
if (phy_on_sfp(phy))
|
||||
pdn->parent_sfp_bus = pdn->upstream.netdev->sfp_bus;
|
||||
break;
|
||||
case PHY_UPSTREAM_PHY:
|
||||
pdn->upstream.phydev = (struct phy_device *)upstream;
|
||||
if (phy_on_sfp(phy))
|
||||
pdn->parent_sfp_bus = pdn->upstream.phydev->sfp_bus;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
pdn->upstream_type = upt;
|
||||
|
||||
/* Attempt to re-use a previously allocated phy_index */
|
||||
if (phy->phyindex) {
|
||||
ret = xa_insert(&topo->phys, phy->phyindex, pdn, GFP_KERNEL);
|
||||
|
||||
/* Errors could be either -ENOMEM or -EBUSY. If the phy has an
|
||||
* index, and there's another entry at the same index, this is
|
||||
* unexpected and we still error-out
|
||||
*/
|
||||
if (ret)
|
||||
goto err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = xa_alloc_cyclic(&topo->phys, &phy->phyindex, pdn, xa_limit_32b,
|
||||
&topo->next_phy_index, GFP_KERNEL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(pdn);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phy_link_topo_add_phy);
|
||||
|
||||
void phy_link_topo_del_phy(struct phy_link_topology *topo,
|
||||
struct phy_device *phy)
|
||||
{
|
||||
struct phy_device_node *pdn = xa_erase(&topo->phys, phy->phyindex);
|
||||
|
||||
/* We delete the PHY from the topology, however we don't re-set the
|
||||
* phy->phyindex field. If the PHY isn't gone, we can re-assign it the
|
||||
* same index next time it's added back to the topology
|
||||
*/
|
||||
|
||||
kfree(pdn);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phy_link_topo_del_phy);
|
||||
@@ -3408,7 +3408,8 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void phylink_sfp_disconnect_phy(void *upstream)
|
||||
static void phylink_sfp_disconnect_phy(void *upstream,
|
||||
struct phy_device *phydev)
|
||||
{
|
||||
phylink_disconnect_phy(upstream);
|
||||
}
|
||||
|
||||
@@ -770,6 +770,8 @@ static const struct sfp_upstream_ops at8031_sfp_ops = {
|
||||
.attach = phy_sfp_attach,
|
||||
.detach = phy_sfp_detach,
|
||||
.module_insert = at8031_sfp_insert,
|
||||
.connect_phy = phy_sfp_connect_phy,
|
||||
.disconnect_phy = phy_sfp_disconnect_phy,
|
||||
};
|
||||
|
||||
static int at8031_parse_dt(struct phy_device *phydev)
|
||||
|
||||
@@ -699,6 +699,8 @@ static const struct sfp_upstream_ops qca807x_sfp_ops = {
|
||||
.detach = phy_sfp_detach,
|
||||
.module_insert = qca807x_sfp_insert,
|
||||
.module_remove = qca807x_sfp_remove,
|
||||
.connect_phy = phy_sfp_connect_phy,
|
||||
.disconnect_phy = phy_sfp_disconnect_phy,
|
||||
};
|
||||
|
||||
static int qca807x_probe(struct phy_device *phydev)
|
||||
|
||||
@@ -486,7 +486,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus)
|
||||
bus->socket_ops->stop(bus->sfp);
|
||||
bus->socket_ops->detach(bus->sfp);
|
||||
if (bus->phydev && ops && ops->disconnect_phy)
|
||||
ops->disconnect_phy(bus->upstream);
|
||||
ops->disconnect_phy(bus->upstream, bus->phydev);
|
||||
}
|
||||
bus->registered = false;
|
||||
}
|
||||
@@ -742,7 +742,7 @@ void sfp_remove_phy(struct sfp_bus *bus)
|
||||
const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
|
||||
|
||||
if (ops && ops->disconnect_phy)
|
||||
ops->disconnect_phy(bus->upstream);
|
||||
ops->disconnect_phy(bus->upstream, bus->phydev);
|
||||
bus->phydev = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_remove_phy);
|
||||
@@ -859,3 +859,14 @@ void sfp_unregister_socket(struct sfp_bus *bus)
|
||||
sfp_bus_put(bus);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_unregister_socket);
|
||||
|
||||
const char *sfp_get_name(struct sfp_bus *bus)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (bus->sfp_dev)
|
||||
return dev_name(bus->sfp_dev);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_get_name);
|
||||
|
||||
+26
-1
@@ -480,6 +480,26 @@ struct ethtool_rmon_stats {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ethtool_ts_stats - HW timestamping statistics
|
||||
* @pkts: Number of packets successfully timestamped by the hardware.
|
||||
* @lost: Number of hardware timestamping requests where the timestamping
|
||||
* information from the hardware never arrived for submission with
|
||||
* the skb.
|
||||
* @err: Number of arbitrary timestamp generation error events that the
|
||||
* hardware encountered, exclusive of @lost statistics. Cases such
|
||||
* as resource exhaustion, unavailability, firmware errors, and
|
||||
* detected illogical timestamp values not submitted with the skb
|
||||
* are inclusive to this counter.
|
||||
*/
|
||||
struct ethtool_ts_stats {
|
||||
struct_group(tx_stats,
|
||||
u64 pkts;
|
||||
u64 lost;
|
||||
u64 err;
|
||||
);
|
||||
};
|
||||
|
||||
#define ETH_MODULE_EEPROM_PAGE_LEN 128
|
||||
#define ETH_MODULE_MAX_I2C_ADDRESS 0x7f
|
||||
|
||||
@@ -755,7 +775,10 @@ struct ethtool_rxfh_param {
|
||||
* @get_ts_info: Get the time stamping and PTP hardware clock capabilities.
|
||||
* It may be called with RCU, or rtnl or reference on the device.
|
||||
* Drivers supporting transmit time stamps in software should set this to
|
||||
* ethtool_op_get_ts_info().
|
||||
* ethtool_op_get_ts_info(). Drivers must not zero statistics which they
|
||||
* don't report. The stats structure is initialized to ETHTOOL_STAT_NOT_SET
|
||||
* indicating driver does not report statistics.
|
||||
* @get_ts_stats: Query the device hardware timestamping statistics.
|
||||
* @get_module_info: Get the size and type of the eeprom contained within
|
||||
* a plug-in module.
|
||||
* @get_module_eeprom: Get the eeprom information from the plug-in module
|
||||
@@ -898,6 +921,8 @@ struct ethtool_ops {
|
||||
struct ethtool_dump *, void *);
|
||||
int (*set_dump)(struct net_device *, struct ethtool_dump *);
|
||||
int (*get_ts_info)(struct net_device *, struct ethtool_ts_info *);
|
||||
void (*get_ts_stats)(struct net_device *dev,
|
||||
struct ethtool_ts_stats *ts_stats);
|
||||
int (*get_module_info)(struct net_device *,
|
||||
struct ethtool_modinfo *);
|
||||
int (*get_module_eeprom)(struct net_device *,
|
||||
|
||||
@@ -9817,7 +9817,21 @@ struct mlx5_ifc_pplm_reg_bits {
|
||||
u8 fec_override_admin_100g_2x[0x10];
|
||||
u8 fec_override_admin_50g_1x[0x10];
|
||||
|
||||
u8 reserved_at_140[0x140];
|
||||
u8 fec_override_cap_800g_8x[0x10];
|
||||
u8 fec_override_cap_400g_4x[0x10];
|
||||
|
||||
u8 fec_override_cap_200g_2x[0x10];
|
||||
u8 fec_override_cap_100g_1x[0x10];
|
||||
|
||||
u8 reserved_at_180[0xa0];
|
||||
|
||||
u8 fec_override_admin_800g_8x[0x10];
|
||||
u8 fec_override_admin_400g_4x[0x10];
|
||||
|
||||
u8 fec_override_admin_200g_2x[0x10];
|
||||
u8 fec_override_admin_100g_1x[0x10];
|
||||
|
||||
u8 reserved_at_260[0x20];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_ppcnt_reg_bits {
|
||||
@@ -10189,7 +10203,9 @@ struct mlx5_ifc_mtutc_reg_bits {
|
||||
};
|
||||
|
||||
struct mlx5_ifc_pcam_enhanced_features_bits {
|
||||
u8 reserved_at_0[0x68];
|
||||
u8 reserved_at_0[0x48];
|
||||
u8 fec_100G_per_lane_in_pplm[0x1];
|
||||
u8 reserved_at_49[0x1f];
|
||||
u8 fec_50G_per_lane_in_pplm[0x1];
|
||||
u8 reserved_at_69[0x4];
|
||||
u8 rx_icrc_encapsulated_counter[0x1];
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <net/dcbnl.h>
|
||||
#endif
|
||||
#include <net/netprio_cgroup.h>
|
||||
|
||||
#include <linux/netdev_features.h>
|
||||
#include <linux/neighbour.h>
|
||||
#include <uapi/linux/netdevice.h>
|
||||
@@ -52,6 +51,7 @@
|
||||
#include <net/net_trackers.h>
|
||||
#include <net/net_debug.h>
|
||||
#include <net/dropreason-core.h>
|
||||
#include <linux/phy_link_topology_core.h>
|
||||
|
||||
struct netpoll_info;
|
||||
struct device;
|
||||
@@ -1974,6 +1974,7 @@ enum netdev_reg_state {
|
||||
* @fcoe_ddp_xid: Max exchange id for FCoE LRO by ddp
|
||||
*
|
||||
* @priomap: XXX: need comments on this one
|
||||
* @link_topo: Physical link topology tracking attached PHYs
|
||||
* @phydev: Physical device may attach itself
|
||||
* for hardware timestamping
|
||||
* @sfp_bus: attached &struct sfp_bus structure.
|
||||
@@ -2362,6 +2363,7 @@ struct net_device {
|
||||
#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
|
||||
struct netprio_map __rcu *priomap;
|
||||
#endif
|
||||
struct phy_link_topology *link_topo;
|
||||
struct phy_device *phydev;
|
||||
struct sfp_bus *sfp_bus;
|
||||
struct lock_class_key *qdisc_tx_busylock;
|
||||
|
||||
@@ -550,6 +550,9 @@ struct macsec_ops;
|
||||
* @drv: Pointer to the driver for this PHY instance
|
||||
* @devlink: Create a link between phy dev and mac dev, if the external phy
|
||||
* used by current mac interface is managed by another mac interface.
|
||||
* @phyindex: Unique id across the phy's parent tree of phys to address the PHY
|
||||
* from userspace, similar to ifindex. A zero index means the PHY
|
||||
* wasn't assigned an id yet.
|
||||
* @phy_id: UID for this device found during discovery
|
||||
* @c45_ids: 802.3-c45 Device Identifiers if is_c45.
|
||||
* @is_c45: Set to true if this PHY uses clause 45 addressing.
|
||||
@@ -650,6 +653,7 @@ struct phy_device {
|
||||
|
||||
struct device_link *devlink;
|
||||
|
||||
u32 phyindex;
|
||||
u32 phy_id;
|
||||
|
||||
struct phy_c45_device_ids c45_ids;
|
||||
@@ -1754,6 +1758,8 @@ int phy_suspend(struct phy_device *phydev);
|
||||
int phy_resume(struct phy_device *phydev);
|
||||
int __phy_resume(struct phy_device *phydev);
|
||||
int phy_loopback(struct phy_device *phydev, bool enable);
|
||||
int phy_sfp_connect_phy(void *upstream, struct phy_device *phy);
|
||||
void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy);
|
||||
void phy_sfp_attach(void *upstream, struct sfp_bus *bus);
|
||||
void phy_sfp_detach(void *upstream, struct sfp_bus *bus);
|
||||
int phy_sfp_probe(struct phy_device *phydev,
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* PHY device list allow maintaining a list of PHY devices that are
|
||||
* part of a netdevice's link topology. PHYs can for example be chained,
|
||||
* as is the case when using a PHY that exposes an SFP module, on which an
|
||||
* SFP transceiver that embeds a PHY is connected.
|
||||
*
|
||||
* This list can then be used by userspace to leverage individual PHY
|
||||
* capabilities.
|
||||
*/
|
||||
#ifndef __PHY_LINK_TOPOLOGY_H
|
||||
#define __PHY_LINK_TOPOLOGY_H
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/phy_link_topology_core.h>
|
||||
|
||||
struct xarray;
|
||||
struct phy_device;
|
||||
struct net_device;
|
||||
struct sfp_bus;
|
||||
|
||||
struct phy_device_node {
|
||||
enum phy_upstream upstream_type;
|
||||
|
||||
union {
|
||||
struct net_device *netdev;
|
||||
struct phy_device *phydev;
|
||||
} upstream;
|
||||
|
||||
struct sfp_bus *parent_sfp_bus;
|
||||
|
||||
struct phy_device *phy;
|
||||
};
|
||||
|
||||
struct phy_link_topology {
|
||||
struct xarray phys;
|
||||
u32 next_phy_index;
|
||||
};
|
||||
|
||||
static inline struct phy_device *
|
||||
phy_link_topo_get_phy(struct phy_link_topology *topo, u32 phyindex)
|
||||
{
|
||||
struct phy_device_node *pdn = xa_load(&topo->phys, phyindex);
|
||||
|
||||
if (pdn)
|
||||
return pdn->phy;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if IS_REACHABLE(CONFIG_PHYLIB)
|
||||
int phy_link_topo_add_phy(struct phy_link_topology *topo,
|
||||
struct phy_device *phy,
|
||||
enum phy_upstream upt, void *upstream);
|
||||
|
||||
void phy_link_topo_del_phy(struct phy_link_topology *lt, struct phy_device *phy);
|
||||
|
||||
#else
|
||||
static inline int phy_link_topo_add_phy(struct phy_link_topology *topo,
|
||||
struct phy_device *phy,
|
||||
enum phy_upstream upt, void *upstream)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void phy_link_topo_del_phy(struct phy_link_topology *topo,
|
||||
struct phy_device *phy)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PHY_LINK_TOPOLOGY_H */
|
||||
@@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __PHY_LINK_TOPOLOGY_CORE_H
|
||||
#define __PHY_LINK_TOPOLOGY_CORE_H
|
||||
|
||||
struct phy_link_topology;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_PHYLIB)
|
||||
|
||||
struct phy_link_topology *phy_link_topo_create(struct net_device *dev);
|
||||
void phy_link_topo_destroy(struct phy_link_topology *topo);
|
||||
|
||||
#else
|
||||
|
||||
static inline struct phy_link_topology *phy_link_topo_create(struct net_device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void phy_link_topo_destroy(struct phy_link_topology *topo)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __PHY_LINK_TOPOLOGY_CORE_H */
|
||||
+7
-1
@@ -544,7 +544,7 @@ struct sfp_upstream_ops {
|
||||
void (*link_down)(void *priv);
|
||||
void (*link_up)(void *priv);
|
||||
int (*connect_phy)(void *priv, struct phy_device *);
|
||||
void (*disconnect_phy)(void *priv);
|
||||
void (*disconnect_phy)(void *priv, struct phy_device *);
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_SFP)
|
||||
@@ -570,6 +570,7 @@ struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode);
|
||||
int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
||||
const struct sfp_upstream_ops *ops);
|
||||
void sfp_bus_del_upstream(struct sfp_bus *bus);
|
||||
const char *sfp_get_name(struct sfp_bus *bus);
|
||||
#else
|
||||
static inline int sfp_parse_port(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id,
|
||||
@@ -648,6 +649,11 @@ static inline int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
||||
static inline void sfp_bus_del_upstream(struct sfp_bus *bus)
|
||||
{
|
||||
}
|
||||
|
||||
static inline const char *sfp_get_name(struct sfp_bus *bus)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+12
-3
@@ -998,7 +998,7 @@ struct sk_buff {
|
||||
#ifdef CONFIG_NETFILTER_SKIP_EGRESS
|
||||
__u8 nf_skip_egress:1;
|
||||
#endif
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
#ifdef CONFIG_SKB_DECRYPTED
|
||||
__u8 decrypted:1;
|
||||
#endif
|
||||
__u8 slow_gro:1;
|
||||
@@ -1621,17 +1621,26 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
|
||||
static inline int skb_cmp_decrypted(const struct sk_buff *skb1,
|
||||
const struct sk_buff *skb2)
|
||||
{
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
#ifdef CONFIG_SKB_DECRYPTED
|
||||
return skb2->decrypted - skb1->decrypted;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool skb_is_decrypted(const struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_SKB_DECRYPTED
|
||||
return skb->decrypted;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void skb_copy_decrypted(struct sk_buff *to,
|
||||
const struct sk_buff *from)
|
||||
{
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
#ifdef CONFIG_SKB_DECRYPTED
|
||||
to->decrypted = from->decrypted;
|
||||
#endif
|
||||
}
|
||||
|
||||
+12
-2
@@ -41,7 +41,8 @@
|
||||
* nlmsg_get_pos() return current position in message
|
||||
* nlmsg_trim() trim part of message
|
||||
* nlmsg_cancel() cancel message construction
|
||||
* nlmsg_free() free a netlink message
|
||||
* nlmsg_consume() free a netlink message (expected)
|
||||
* nlmsg_free() free a netlink message (drop)
|
||||
*
|
||||
* Message Sending:
|
||||
* nlmsg_multicast() multicast message to several groups
|
||||
@@ -1082,7 +1083,7 @@ static inline void nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
}
|
||||
|
||||
/**
|
||||
* nlmsg_free - free a netlink message
|
||||
* nlmsg_free - drop a netlink message
|
||||
* @skb: socket buffer of netlink message
|
||||
*/
|
||||
static inline void nlmsg_free(struct sk_buff *skb)
|
||||
@@ -1090,6 +1091,15 @@ static inline void nlmsg_free(struct sk_buff *skb)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* nlmsg_consume - free a netlink message
|
||||
* @skb: socket buffer of netlink message
|
||||
*/
|
||||
static inline void nlmsg_consume(struct sk_buff *skb)
|
||||
{
|
||||
consume_skb(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* nlmsg_multicast_filtered - multicast a netlink message with filter function
|
||||
* @sk: netlink socket to spread messages to
|
||||
|
||||
+1
-3
@@ -2837,12 +2837,10 @@ static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
|
||||
|
||||
if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) {
|
||||
skb = sk->sk_validate_xmit_skb(sk, dev, skb);
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
} else if (unlikely(skb->decrypted)) {
|
||||
} else if (unlikely(skb_is_decrypted(skb))) {
|
||||
pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n");
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ TRACE_EVENT_CONDITION(mdio_access,
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy(__entry->busid, bus->id, MII_BUS_ID_SIZE);
|
||||
strscpy(__entry->busid, bus->id, MII_BUS_ID_SIZE);
|
||||
__entry->read = read;
|
||||
__entry->addr = addr;
|
||||
__entry->regnum = regnum;
|
||||
|
||||
@@ -110,7 +110,7 @@ TRACE_EVENT(sock_exceed_buf_limit,
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy(__entry->name, prot->name, 32);
|
||||
strscpy(__entry->name, prot->name, 32);
|
||||
__entry->sysctl_mem[0] = READ_ONCE(prot->sysctl_mem[0]);
|
||||
__entry->sysctl_mem[1] = READ_ONCE(prot->sysctl_mem[1]);
|
||||
__entry->sysctl_mem[2] = READ_ONCE(prot->sysctl_mem[2]);
|
||||
|
||||
@@ -2268,4 +2268,20 @@ struct ethtool_link_settings {
|
||||
* __u32 map_lp_advertising[link_mode_masks_nwords];
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* enum phy_upstream - Represents the upstream component a given PHY device
|
||||
* is connected to, as in what is on the other end of the MII bus. Most PHYs
|
||||
* will be attached to an Ethernet MAC controller, but in some cases, there's
|
||||
* an intermediate PHY used as a media-converter, which will driver another
|
||||
* MII interface as its output.
|
||||
* @PHY_UPSTREAM_MAC: Upstream component is a MAC (a switch port,
|
||||
* or ethernet controller)
|
||||
* @PHY_UPSTREAM_PHY: Upstream component is a PHY (likely a media converter)
|
||||
*/
|
||||
enum phy_upstream {
|
||||
PHY_UPSTREAM_MAC,
|
||||
PHY_UPSTREAM_PHY,
|
||||
};
|
||||
|
||||
#endif /* _UAPI_LINUX_ETHTOOL_H */
|
||||
|
||||
@@ -117,12 +117,11 @@ enum {
|
||||
|
||||
/* request header */
|
||||
|
||||
/* use compact bitsets in reply */
|
||||
#define ETHTOOL_FLAG_COMPACT_BITSETS (1 << 0)
|
||||
/* provide optional reply for SET or ACT requests */
|
||||
#define ETHTOOL_FLAG_OMIT_REPLY (1 << 1)
|
||||
/* request statistics, if supported by the driver */
|
||||
#define ETHTOOL_FLAG_STATS (1 << 2)
|
||||
enum ethtool_header_flags {
|
||||
ETHTOOL_FLAG_COMPACT_BITSETS = 1 << 0, /* use compact bitsets in reply */
|
||||
ETHTOOL_FLAG_OMIT_REPLY = 1 << 1, /* provide optional reply for SET or ACT requests */
|
||||
ETHTOOL_FLAG_STATS = 1 << 2, /* request statistics, if supported by the driver */
|
||||
};
|
||||
|
||||
#define ETHTOOL_FLAG_ALL (ETHTOOL_FLAG_COMPACT_BITSETS | \
|
||||
ETHTOOL_FLAG_OMIT_REPLY | \
|
||||
@@ -133,6 +132,7 @@ enum {
|
||||
ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */
|
||||
ETHTOOL_A_HEADER_DEV_NAME, /* string */
|
||||
ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */
|
||||
ETHTOOL_A_HEADER_PHY_INDEX, /* u32 */
|
||||
|
||||
/* add new constants above here */
|
||||
__ETHTOOL_A_HEADER_CNT,
|
||||
@@ -478,12 +478,26 @@ enum {
|
||||
ETHTOOL_A_TSINFO_TX_TYPES, /* bitset */
|
||||
ETHTOOL_A_TSINFO_RX_FILTERS, /* bitset */
|
||||
ETHTOOL_A_TSINFO_PHC_INDEX, /* u32 */
|
||||
ETHTOOL_A_TSINFO_STATS, /* nest - _A_TSINFO_STAT */
|
||||
|
||||
/* add new constants above here */
|
||||
__ETHTOOL_A_TSINFO_CNT,
|
||||
ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
ETHTOOL_A_TS_STAT_UNSPEC,
|
||||
|
||||
ETHTOOL_A_TS_STAT_TX_PKTS, /* u64 */
|
||||
ETHTOOL_A_TS_STAT_TX_LOST, /* u64 */
|
||||
ETHTOOL_A_TS_STAT_TX_ERR, /* u64 */
|
||||
|
||||
/* add new constants above here */
|
||||
__ETHTOOL_A_TS_STAT_CNT,
|
||||
ETHTOOL_A_TS_STAT_MAX = (__ETHTOOL_A_TS_STAT_CNT - 1)
|
||||
|
||||
};
|
||||
|
||||
/* PHC VCLOCKS */
|
||||
|
||||
enum {
|
||||
|
||||
@@ -60,6 +60,9 @@ config NET_XGRESS
|
||||
config NET_REDIRECT
|
||||
bool
|
||||
|
||||
config SKB_DECRYPTED
|
||||
bool
|
||||
|
||||
config SKB_EXTENSIONS
|
||||
bool
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@
|
||||
#include <net/page_pool/helpers.h>
|
||||
#include <net/rps.h>
|
||||
#include <trace/hooks/net.h>
|
||||
#include <linux/phy_link_topology_core.h>
|
||||
|
||||
#include "dev.h"
|
||||
#include "net-sysfs.h"
|
||||
@@ -10975,6 +10976,12 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
|
||||
#ifdef CONFIG_NET_SCHED
|
||||
hash_init(dev->qdisc_hash);
|
||||
#endif
|
||||
dev->link_topo = phy_link_topo_create(dev);
|
||||
if (IS_ERR(dev->link_topo)) {
|
||||
dev->link_topo = NULL;
|
||||
goto free_all;
|
||||
}
|
||||
|
||||
dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
|
||||
setup(dev);
|
||||
|
||||
@@ -11063,6 +11070,8 @@ void free_netdev(struct net_device *dev)
|
||||
free_percpu(dev->xdp_bulkq);
|
||||
dev->xdp_bulkq = NULL;
|
||||
|
||||
phy_link_topo_destroy(dev->link_topo);
|
||||
|
||||
/* Compatibility with error handling in drivers */
|
||||
if (dev->reg_state == NETREG_UNINITIALIZED) {
|
||||
netdev_freemem(dev);
|
||||
|
||||
+2
-3
@@ -2526,13 +2526,12 @@ EXPORT_SYMBOL(skb_set_owner_w);
|
||||
|
||||
static bool can_skb_orphan_partial(const struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
/* Drivers depend on in-order delivery for crypto offload,
|
||||
* partial orphan breaks out-of-order-OK logic.
|
||||
*/
|
||||
if (skb->decrypted)
|
||||
if (skb_is_decrypted(skb))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return (skb->destructor == sock_wfree ||
|
||||
(IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree));
|
||||
}
|
||||
|
||||
+1
-1
@@ -1214,7 +1214,7 @@ static void __devlink_compat_running_version(struct devlink *devlink,
|
||||
}
|
||||
}
|
||||
free_msg:
|
||||
nlmsg_free(msg);
|
||||
nlmsg_consume(msg);
|
||||
}
|
||||
|
||||
void devlink_compat_running_version(struct devlink *devlink,
|
||||
|
||||
+46
-2
@@ -4,6 +4,7 @@
|
||||
#include <linux/ethtool_netlink.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "netlink.h"
|
||||
#include <linux/phy_link_topology.h>
|
||||
|
||||
static struct genl_family ethtool_genl_family;
|
||||
|
||||
@@ -30,6 +31,24 @@ const struct nla_policy ethnl_header_policy_stats[] = {
|
||||
ETHTOOL_FLAGS_STATS),
|
||||
};
|
||||
|
||||
const struct nla_policy ethnl_header_policy_phy[] = {
|
||||
[ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
|
||||
[ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
|
||||
.len = ALTIFNAMSIZ - 1 },
|
||||
[ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
|
||||
ETHTOOL_FLAGS_BASIC),
|
||||
[ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1),
|
||||
};
|
||||
|
||||
const struct nla_policy ethnl_header_policy_phy_stats[] = {
|
||||
[ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
|
||||
[ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
|
||||
.len = ALTIFNAMSIZ - 1 },
|
||||
[ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
|
||||
ETHTOOL_FLAGS_STATS),
|
||||
[ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1),
|
||||
};
|
||||
|
||||
int ethnl_ops_begin(struct net_device *dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -89,8 +108,9 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
|
||||
const struct nlattr *header, struct net *net,
|
||||
struct netlink_ext_ack *extack, bool require_dev)
|
||||
{
|
||||
struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy)];
|
||||
struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy_phy)];
|
||||
const struct nlattr *devname_attr;
|
||||
struct phy_device *phydev = NULL;
|
||||
struct net_device *dev = NULL;
|
||||
u32 flags = 0;
|
||||
int ret;
|
||||
@@ -104,7 +124,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
|
||||
/* No validation here, command policy should have a nested policy set
|
||||
* for the header, therefore validation should have already been done.
|
||||
*/
|
||||
ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy) - 1, header,
|
||||
ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy_phy) - 1, header,
|
||||
NULL, extack);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -145,6 +165,30 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
if (tb[ETHTOOL_A_HEADER_PHY_INDEX]) {
|
||||
struct nlattr *phy_id;
|
||||
|
||||
phy_id = tb[ETHTOOL_A_HEADER_PHY_INDEX];
|
||||
phydev = phy_link_topo_get_phy(dev->link_topo,
|
||||
nla_get_u32(phy_id));
|
||||
if (!phydev) {
|
||||
NL_SET_BAD_ATTR(extack, phy_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
/* If we need a PHY but no phy index is specified, fallback
|
||||
* to dev->phydev
|
||||
*/
|
||||
phydev = dev->phydev;
|
||||
}
|
||||
} else if (tb[ETHTOOL_A_HEADER_PHY_INDEX]) {
|
||||
NL_SET_ERR_MSG_ATTR(extack, header,
|
||||
"can't target a PHY without a netdev");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req_info->phydev = phydev;
|
||||
req_info->dev = dev;
|
||||
req_info->flags = flags;
|
||||
return 0;
|
||||
|
||||
@@ -250,6 +250,7 @@ static inline unsigned int ethnl_reply_header_size(void)
|
||||
* @dev: network device the request is for (may be null)
|
||||
* @dev_tracker: refcount tracker for @dev reference
|
||||
* @flags: request flags common for all request types
|
||||
* @phydev: phy_device connected to @dev this request is for (may be null)
|
||||
*
|
||||
* This is a common base for request specific structures holding data from
|
||||
* parsed userspace request. These always embed struct ethnl_req_info at
|
||||
@@ -259,6 +260,7 @@ struct ethnl_req_info {
|
||||
struct net_device *dev;
|
||||
netdevice_tracker dev_tracker;
|
||||
u32 flags;
|
||||
struct phy_device *phydev;
|
||||
};
|
||||
|
||||
static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info)
|
||||
@@ -395,9 +397,12 @@ extern const struct ethnl_request_ops ethnl_rss_request_ops;
|
||||
extern const struct ethnl_request_ops ethnl_plca_cfg_request_ops;
|
||||
extern const struct ethnl_request_ops ethnl_plca_status_request_ops;
|
||||
extern const struct ethnl_request_ops ethnl_mm_request_ops;
|
||||
extern const struct ethnl_request_ops ethnl_phy_request_ops;
|
||||
|
||||
extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
|
||||
extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
|
||||
extern const struct nla_policy ethnl_header_policy_phy[ETHTOOL_A_HEADER_PHY_INDEX + 1];
|
||||
extern const struct nla_policy ethnl_header_policy_phy_stats[ETHTOOL_A_HEADER_PHY_INDEX + 1];
|
||||
extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_COUNTS_ONLY + 1];
|
||||
extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1];
|
||||
extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1];
|
||||
|
||||
+51
-1
@@ -13,14 +13,18 @@ struct tsinfo_req_info {
|
||||
struct tsinfo_reply_data {
|
||||
struct ethnl_reply_data base;
|
||||
struct ethtool_ts_info ts_info;
|
||||
struct ethtool_ts_stats stats;
|
||||
};
|
||||
|
||||
#define TSINFO_REPDATA(__reply_base) \
|
||||
container_of(__reply_base, struct tsinfo_reply_data, base)
|
||||
|
||||
#define ETHTOOL_TS_STAT_CNT \
|
||||
(__ETHTOOL_A_TS_STAT_CNT - (ETHTOOL_A_TS_STAT_UNSPEC + 1))
|
||||
|
||||
const struct nla_policy ethnl_tsinfo_get_policy[] = {
|
||||
[ETHTOOL_A_TSINFO_HEADER] =
|
||||
NLA_POLICY_NESTED(ethnl_header_policy),
|
||||
NLA_POLICY_NESTED(ethnl_header_policy_stats),
|
||||
};
|
||||
|
||||
static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
|
||||
@@ -34,6 +38,12 @@ static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
|
||||
ret = ethnl_ops_begin(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (req_base->flags & ETHTOOL_FLAG_STATS &&
|
||||
dev->ethtool_ops->get_ts_stats) {
|
||||
ethtool_stats_init((u64 *)&data->stats,
|
||||
sizeof(data->stats) / sizeof(u64));
|
||||
dev->ethtool_ops->get_ts_stats(dev, &data->stats);
|
||||
}
|
||||
ret = __ethtool_get_ts_info(dev, &data->ts_info);
|
||||
ethnl_ops_complete(dev);
|
||||
|
||||
@@ -79,10 +89,47 @@ static int tsinfo_reply_size(const struct ethnl_req_info *req_base,
|
||||
}
|
||||
if (ts_info->phc_index >= 0)
|
||||
len += nla_total_size(sizeof(u32)); /* _TSINFO_PHC_INDEX */
|
||||
if (req_base->flags & ETHTOOL_FLAG_STATS)
|
||||
len += nla_total_size(0) + /* _TSINFO_STATS */
|
||||
nla_total_size_64bit(sizeof(u64)) * ETHTOOL_TS_STAT_CNT;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int tsinfo_put_stat(struct sk_buff *skb, u64 val, u16 attrtype)
|
||||
{
|
||||
if (val == ETHTOOL_STAT_NOT_SET)
|
||||
return 0;
|
||||
if (nla_put_uint(skb, attrtype, val))
|
||||
return -EMSGSIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsinfo_put_stats(struct sk_buff *skb,
|
||||
const struct ethtool_ts_stats *stats)
|
||||
{
|
||||
struct nlattr *nest;
|
||||
|
||||
nest = nla_nest_start(skb, ETHTOOL_A_TSINFO_STATS);
|
||||
if (!nest)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (tsinfo_put_stat(skb, stats->tx_stats.pkts,
|
||||
ETHTOOL_A_TS_STAT_TX_PKTS) ||
|
||||
tsinfo_put_stat(skb, stats->tx_stats.lost,
|
||||
ETHTOOL_A_TS_STAT_TX_LOST) ||
|
||||
tsinfo_put_stat(skb, stats->tx_stats.err,
|
||||
ETHTOOL_A_TS_STAT_TX_ERR))
|
||||
goto err_cancel;
|
||||
|
||||
nla_nest_end(skb, nest);
|
||||
return 0;
|
||||
|
||||
err_cancel:
|
||||
nla_nest_cancel(skb, nest);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int tsinfo_fill_reply(struct sk_buff *skb,
|
||||
const struct ethnl_req_info *req_base,
|
||||
const struct ethnl_reply_data *reply_base)
|
||||
@@ -119,6 +166,9 @@ static int tsinfo_fill_reply(struct sk_buff *skb,
|
||||
if (ts_info->phc_index >= 0 &&
|
||||
nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX, ts_info->phc_index))
|
||||
return -EMSGSIZE;
|
||||
if (req_base->flags & ETHTOOL_FLAG_STATS &&
|
||||
tsinfo_put_stats(skb, &data->stats))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -462,7 +462,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
/* Try to redo what tcp_v4_send_synack did. */
|
||||
req->rsk_window_clamp = tp->window_clamp ? :dst_metric(&rt->dst, RTAX_WINDOW);
|
||||
req->rsk_window_clamp = READ_ONCE(tp->window_clamp) ? :
|
||||
dst_metric(&rt->dst, RTAX_WINDOW);
|
||||
/* limit the window selection if the user enforce a smaller rx buffer */
|
||||
full_space = tcp_full_space(sk);
|
||||
if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
|
||||
|
||||
+4
-4
@@ -1721,7 +1721,7 @@ int tcp_set_rcvlowat(struct sock *sk, int val)
|
||||
space = tcp_space_from_win(sk, val);
|
||||
if (space > sk->sk_rcvbuf) {
|
||||
WRITE_ONCE(sk->sk_rcvbuf, space);
|
||||
tcp_sk(sk)->window_clamp = val;
|
||||
WRITE_ONCE(tcp_sk(sk)->window_clamp, val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3379,7 +3379,7 @@ int tcp_set_window_clamp(struct sock *sk, int val)
|
||||
if (!val) {
|
||||
if (sk->sk_state != TCP_CLOSE)
|
||||
return -EINVAL;
|
||||
tp->window_clamp = 0;
|
||||
WRITE_ONCE(tp->window_clamp, 0);
|
||||
} else {
|
||||
u32 new_rcv_ssthresh, old_window_clamp = tp->window_clamp;
|
||||
u32 new_window_clamp = val < SOCK_MIN_RCVBUF / 2 ?
|
||||
@@ -3388,7 +3388,7 @@ int tcp_set_window_clamp(struct sock *sk, int val)
|
||||
if (new_window_clamp == old_window_clamp)
|
||||
return 0;
|
||||
|
||||
tp->window_clamp = new_window_clamp;
|
||||
WRITE_ONCE(tp->window_clamp, new_window_clamp);
|
||||
if (new_window_clamp < old_window_clamp) {
|
||||
/* need to apply the reserved mem provisioning only
|
||||
* when shrinking the window clamp
|
||||
@@ -4057,7 +4057,7 @@ int do_tcp_getsockopt(struct sock *sk, int level,
|
||||
TCP_RTO_MAX / HZ);
|
||||
break;
|
||||
case TCP_WINDOW_CLAMP:
|
||||
val = tp->window_clamp;
|
||||
val = READ_ONCE(tp->window_clamp);
|
||||
break;
|
||||
case TCP_INFO: {
|
||||
struct tcp_info info;
|
||||
|
||||
+13
-16
@@ -563,19 +563,20 @@ static void tcp_init_buffer_space(struct sock *sk)
|
||||
maxwin = tcp_full_space(sk);
|
||||
|
||||
if (tp->window_clamp >= maxwin) {
|
||||
tp->window_clamp = maxwin;
|
||||
WRITE_ONCE(tp->window_clamp, maxwin);
|
||||
|
||||
if (tcp_app_win && maxwin > 4 * tp->advmss)
|
||||
tp->window_clamp = max(maxwin -
|
||||
(maxwin >> tcp_app_win),
|
||||
4 * tp->advmss);
|
||||
WRITE_ONCE(tp->window_clamp,
|
||||
max(maxwin - (maxwin >> tcp_app_win),
|
||||
4 * tp->advmss));
|
||||
}
|
||||
|
||||
/* Force reservation of one segment. */
|
||||
if (tcp_app_win &&
|
||||
tp->window_clamp > 2 * tp->advmss &&
|
||||
tp->window_clamp + tp->advmss > maxwin)
|
||||
tp->window_clamp = max(2 * tp->advmss, maxwin - tp->advmss);
|
||||
WRITE_ONCE(tp->window_clamp,
|
||||
max(2 * tp->advmss, maxwin - tp->advmss));
|
||||
|
||||
tp->rcv_ssthresh = min(tp->rcv_ssthresh, tp->window_clamp);
|
||||
tp->snd_cwnd_stamp = tcp_jiffies32;
|
||||
@@ -773,7 +774,8 @@ void tcp_rcv_space_adjust(struct sock *sk)
|
||||
WRITE_ONCE(sk->sk_rcvbuf, rcvbuf);
|
||||
|
||||
/* Make the window clamp follow along. */
|
||||
tp->window_clamp = tcp_win_from_space(sk, rcvbuf);
|
||||
WRITE_ONCE(tp->window_clamp,
|
||||
tcp_win_from_space(sk, rcvbuf));
|
||||
}
|
||||
}
|
||||
tp->rcvq_space.space = copied;
|
||||
@@ -4803,10 +4805,8 @@ static bool tcp_try_coalesce(struct sock *sk,
|
||||
if (!mptcp_skb_can_collapse(to, from))
|
||||
return false;
|
||||
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
if (from->decrypted != to->decrypted)
|
||||
if (skb_cmp_decrypted(from, to))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!skb_try_coalesce(to, from, fragstolen, &delta))
|
||||
return false;
|
||||
@@ -5375,9 +5375,7 @@ restart:
|
||||
break;
|
||||
|
||||
memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
nskb->decrypted = skb->decrypted;
|
||||
#endif
|
||||
skb_copy_decrypted(nskb, skb);
|
||||
TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
|
||||
if (list)
|
||||
__skb_queue_before(list, skb, nskb);
|
||||
@@ -5407,10 +5405,8 @@ restart:
|
||||
!mptcp_skb_can_collapse(nskb, skb) ||
|
||||
(TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)))
|
||||
goto end;
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
if (skb->decrypted != nskb->decrypted)
|
||||
if (skb_cmp_decrypted(skb, nskb))
|
||||
goto end;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6426,7 +6422,8 @@ consume:
|
||||
|
||||
if (!tp->rx_opt.wscale_ok) {
|
||||
tp->rx_opt.snd_wscale = tp->rx_opt.rcv_wscale = 0;
|
||||
tp->window_clamp = min(tp->window_clamp, 65535U);
|
||||
WRITE_ONCE(tp->window_clamp,
|
||||
min(tp->window_clamp, 65535U));
|
||||
}
|
||||
|
||||
if (tp->rx_opt.saw_tstamp) {
|
||||
|
||||
+1
-3
@@ -2050,10 +2050,8 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,
|
||||
TCP_SKB_CB(skb)->tcp_flags) & TCPHDR_ACK) ||
|
||||
((TCP_SKB_CB(tail)->tcp_flags ^
|
||||
TCP_SKB_CB(skb)->tcp_flags) & (TCPHDR_ECE | TCPHDR_CWR)) ||
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
tail->decrypted != skb->decrypted ||
|
||||
#endif
|
||||
!mptcp_skb_can_collapse(tail, skb) ||
|
||||
skb_cmp_decrypted(tail, skb) ||
|
||||
thtail->doff != th->doff ||
|
||||
memcmp(thtail + 1, th + 1, hdrlen - sizeof(*th)))
|
||||
goto no_coalesce;
|
||||
|
||||
@@ -265,9 +265,7 @@ found:
|
||||
flush |= (len - 1) >= mss;
|
||||
|
||||
flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq);
|
||||
#ifdef CONFIG_TLS_DEVICE
|
||||
flush |= p->decrypted ^ skb->decrypted;
|
||||
#endif
|
||||
flush |= skb_cmp_decrypted(p, skb);
|
||||
|
||||
if (flush || skb_gro_receive(p, skb)) {
|
||||
mss = 1;
|
||||
|
||||
+10
-8
@@ -203,16 +203,17 @@ static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt)
|
||||
* This MUST be enforced by all callers.
|
||||
*/
|
||||
void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss,
|
||||
__u32 *rcv_wnd, __u32 *window_clamp,
|
||||
__u32 *rcv_wnd, __u32 *__window_clamp,
|
||||
int wscale_ok, __u8 *rcv_wscale,
|
||||
__u32 init_rcv_wnd)
|
||||
{
|
||||
unsigned int space = (__space < 0 ? 0 : __space);
|
||||
u32 window_clamp = READ_ONCE(*__window_clamp);
|
||||
|
||||
/* If no clamp set the clamp to the max possible scaled window */
|
||||
if (*window_clamp == 0)
|
||||
(*window_clamp) = (U16_MAX << TCP_MAX_WSCALE);
|
||||
space = min(*window_clamp, space);
|
||||
if (window_clamp == 0)
|
||||
window_clamp = (U16_MAX << TCP_MAX_WSCALE);
|
||||
space = min(window_clamp, space);
|
||||
|
||||
/* Quantize space offering to a multiple of mss if possible. */
|
||||
if (space > mss)
|
||||
@@ -239,12 +240,13 @@ void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss,
|
||||
/* Set window scaling on max possible window */
|
||||
space = max_t(u32, space, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2]));
|
||||
space = max_t(u32, space, READ_ONCE(sysctl_rmem_max));
|
||||
space = min_t(u32, space, *window_clamp);
|
||||
space = min_t(u32, space, window_clamp);
|
||||
*rcv_wscale = clamp_t(int, ilog2(space) - 15,
|
||||
0, TCP_MAX_WSCALE);
|
||||
}
|
||||
/* Set the clamp no higher than max representable value */
|
||||
(*window_clamp) = min_t(__u32, U16_MAX << (*rcv_wscale), *window_clamp);
|
||||
WRITE_ONCE(*__window_clamp,
|
||||
min_t(__u32, U16_MAX << (*rcv_wscale), window_clamp));
|
||||
}
|
||||
EXPORT_SYMBOL(tcp_select_initial_window);
|
||||
|
||||
@@ -3857,7 +3859,7 @@ static void tcp_connect_init(struct sock *sk)
|
||||
tcp_ca_dst_init(sk, dst);
|
||||
|
||||
if (!tp->window_clamp)
|
||||
tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
|
||||
WRITE_ONCE(tp->window_clamp, dst_metric(dst, RTAX_WINDOW));
|
||||
tp->advmss = tcp_mss_clamp(tp, dst_metric_advmss(dst));
|
||||
|
||||
tcp_initialize_rcv_mss(sk);
|
||||
@@ -3865,7 +3867,7 @@ static void tcp_connect_init(struct sock *sk)
|
||||
/* limit the window selection if the user enforce a smaller rx buffer */
|
||||
if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
|
||||
(tp->window_clamp > tcp_full_space(sk) || tp->window_clamp == 0))
|
||||
tp->window_clamp = tcp_full_space(sk);
|
||||
WRITE_ONCE(tp->window_clamp, tcp_full_space(sk));
|
||||
|
||||
rcv_wnd = tcp_rwnd_init_bpf(sk);
|
||||
if (rcv_wnd == 0)
|
||||
|
||||
@@ -246,7 +246,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
req->rsk_window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
|
||||
req->rsk_window_clamp = READ_ONCE(tp->window_clamp) ? :dst_metric(dst, RTAX_WINDOW);
|
||||
/* limit the window selection if the user enforce a smaller rx buffer */
|
||||
full_space = tcp_full_space(sk);
|
||||
if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
|
||||
|
||||
@@ -2056,7 +2056,7 @@ static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied)
|
||||
ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
slow = lock_sock_fast(ssk);
|
||||
WRITE_ONCE(ssk->sk_rcvbuf, rcvbuf);
|
||||
tcp_sk(ssk)->window_clamp = window_clamp;
|
||||
WRITE_ONCE(tcp_sk(ssk)->window_clamp, window_clamp);
|
||||
tcp_cleanup_rbuf(ssk, 1);
|
||||
unlock_sock_fast(ssk, slow);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1523,7 +1523,7 @@ int mptcp_set_rcvlowat(struct sock *sk, int val)
|
||||
|
||||
slow = lock_sock_fast(ssk);
|
||||
WRITE_ONCE(ssk->sk_rcvbuf, space);
|
||||
tcp_sk(ssk)->window_clamp = val;
|
||||
WRITE_ONCE(tcp_sk(ssk)->window_clamp, val);
|
||||
unlock_sock_fast(ssk, slow);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -20,6 +20,7 @@ config TLS
|
||||
config TLS_DEVICE
|
||||
bool "Transport Layer Security HW offload"
|
||||
depends on TLS
|
||||
select SKB_DECRYPTED
|
||||
select SOCK_VALIDATE_XMIT
|
||||
select SOCK_RX_QUEUE_MAPPING
|
||||
default n
|
||||
|
||||
@@ -324,7 +324,13 @@ def main():
|
||||
return
|
||||
|
||||
if args.show_time_stamping:
|
||||
tsinfo = dumpit(ynl, args, 'tsinfo-get')
|
||||
req = {
|
||||
'header': {
|
||||
'flags': 'stats',
|
||||
},
|
||||
}
|
||||
|
||||
tsinfo = dumpit(ynl, args, 'tsinfo-get', req)
|
||||
|
||||
print(f'Time stamping parameters for {args.device}:')
|
||||
|
||||
@@ -338,6 +344,9 @@ def main():
|
||||
|
||||
print('Hardware Receive Filter Modes:')
|
||||
[print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])]
|
||||
|
||||
print('Statistics:')
|
||||
[print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()]
|
||||
return
|
||||
|
||||
print(f'Settings for {args.device}:')
|
||||
|
||||
@@ -632,15 +632,28 @@ class YnlFamily(SpecFamily):
|
||||
decoded = self._formatted_string(decoded, attr_spec.display_hint)
|
||||
return decoded
|
||||
|
||||
def _decode_array_nest(self, attr, attr_spec):
|
||||
def _decode_array_attr(self, attr, attr_spec):
|
||||
decoded = []
|
||||
offset = 0
|
||||
while offset < len(attr.raw):
|
||||
item = NlAttr(attr.raw, offset)
|
||||
offset += item.full_len
|
||||
|
||||
subattrs = self._decode(NlAttrs(item.raw), attr_spec['nested-attributes'])
|
||||
decoded.append({ item.type: subattrs })
|
||||
if attr_spec["sub-type"] == 'nest':
|
||||
subattrs = self._decode(NlAttrs(item.raw), attr_spec['nested-attributes'])
|
||||
decoded.append({ item.type: subattrs })
|
||||
elif attr_spec["sub-type"] == 'binary':
|
||||
subattrs = item.as_bin()
|
||||
if attr_spec.display_hint:
|
||||
subattrs = self._formatted_string(subattrs, attr_spec.display_hint)
|
||||
decoded.append(subattrs)
|
||||
elif attr_spec["sub-type"] in NlAttr.type_formats:
|
||||
subattrs = item.as_scalar(attr_spec['sub-type'], attr_spec.byte_order)
|
||||
if attr_spec.display_hint:
|
||||
subattrs = self._formatted_string(subattrs, attr_spec.display_hint)
|
||||
decoded.append(subattrs)
|
||||
else:
|
||||
raise Exception(f'Unknown {attr_spec["sub-type"]} with name {attr_spec["name"]}')
|
||||
return decoded
|
||||
|
||||
def _decode_nest_type_value(self, attr, attr_spec):
|
||||
@@ -734,8 +747,8 @@ class YnlFamily(SpecFamily):
|
||||
decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order)
|
||||
if 'enum' in attr_spec:
|
||||
decoded = self._decode_enum(decoded, attr_spec)
|
||||
elif attr_spec["type"] == 'array-nest':
|
||||
decoded = self._decode_array_nest(attr, attr_spec)
|
||||
elif attr_spec["type"] == 'indexed-array':
|
||||
decoded = self._decode_array_attr(attr, attr_spec)
|
||||
elif attr_spec["type"] == 'bitfield32':
|
||||
value, selector = struct.unpack("II", attr.raw)
|
||||
if 'enum' in attr_spec:
|
||||
|
||||
@@ -841,8 +841,11 @@ class AttrSet(SpecAttrSet):
|
||||
t = TypeBitfield32(self.family, self, elem, value)
|
||||
elif elem['type'] == 'nest':
|
||||
t = TypeNest(self.family, self, elem, value)
|
||||
elif elem['type'] == 'array-nest':
|
||||
t = TypeArrayNest(self.family, self, elem, value)
|
||||
elif elem['type'] == 'indexed-array' and 'sub-type' in elem:
|
||||
if elem["sub-type"] == 'nest':
|
||||
t = TypeArrayNest(self.family, self, elem, value)
|
||||
else:
|
||||
raise Exception(f'new_attr: unsupported sub-type {elem["sub-type"]}')
|
||||
elif elem['type'] == 'nest-type-value':
|
||||
t = TypeNestTypeValue(self.family, self, elem, value)
|
||||
else:
|
||||
@@ -1055,7 +1058,7 @@ class Family(SpecFamily):
|
||||
if nested in self.root_sets:
|
||||
raise Exception("Inheriting members to a space used as root not supported")
|
||||
inherit.update(set(spec['type-value']))
|
||||
elif spec['type'] == 'array-nest':
|
||||
elif spec['type'] == 'indexed-array':
|
||||
inherit.add('idx')
|
||||
self.pure_nested_structs[nested].set_inherited(inherit)
|
||||
|
||||
@@ -1619,9 +1622,12 @@ def _multi_parse(ri, struct, init_lines, local_vars):
|
||||
multi_attrs = set()
|
||||
needs_parg = False
|
||||
for arg, aspec in struct.member_list():
|
||||
if aspec['type'] == 'array-nest':
|
||||
local_vars.append(f'const struct nlattr *attr_{aspec.c_name};')
|
||||
array_nests.add(arg)
|
||||
if aspec['type'] == 'indexed-array' and 'sub-type' in aspec:
|
||||
if aspec["sub-type"] == 'nest':
|
||||
local_vars.append(f'const struct nlattr *attr_{aspec.c_name};')
|
||||
array_nests.add(arg)
|
||||
else:
|
||||
raise Exception(f'Not supported sub-type {aspec["sub-type"]}')
|
||||
if 'multi-attr' in aspec:
|
||||
multi_attrs.add(arg)
|
||||
needs_parg |= 'nested-attributes' in aspec
|
||||
|
||||
Reference in New Issue
Block a user