This converts instances of bitmap_foo(args..., __ETHTOOL_LINK_MODE_MASK_NBITS) to linkmode_foo(args...) I manually fixed up some lines to prevent them from being excessively long. Otherwise, this change was generated with the following semantic patch: // Generated with // echo linux/linkmode.h > includes // git grep -Flf includes include/ | cut -f 2- -d / | cat includes - \ // | sort | uniq | tee new_includes | wc -l && mv new_includes includes // and repeating until the number stopped going up @i@ @@ ( #include <linux/acpi_mdio.h> | #include <linux/brcmphy.h> | #include <linux/dsa/loop.h> | #include <linux/dsa/sja1105.h> | #include <linux/ethtool.h> | #include <linux/ethtool_netlink.h> | #include <linux/fec.h> | #include <linux/fs_enet_pd.h> | #include <linux/fsl/enetc_mdio.h> | #include <linux/fwnode_mdio.h> | #include <linux/linkmode.h> | #include <linux/lsm_audit.h> | #include <linux/mdio-bitbang.h> | #include <linux/mdio.h> | #include <linux/mdio-mux.h> | #include <linux/mii.h> | #include <linux/mii_timestamper.h> | #include <linux/mlx5/accel.h> | #include <linux/mlx5/cq.h> | #include <linux/mlx5/device.h> | #include <linux/mlx5/driver.h> | #include <linux/mlx5/eswitch.h> | #include <linux/mlx5/fs.h> | #include <linux/mlx5/port.h> | #include <linux/mlx5/qp.h> | #include <linux/mlx5/rsc_dump.h> | #include <linux/mlx5/transobj.h> | #include <linux/mlx5/vport.h> | #include <linux/of_mdio.h> | #include <linux/of_net.h> | #include <linux/pcs-lynx.h> | #include <linux/pcs/pcs-xpcs.h> | #include <linux/phy.h> | #include <linux/phy_led_triggers.h> | #include <linux/phylink.h> | #include <linux/platform_data/bcmgenet.h> | #include <linux/platform_data/xilinx-ll-temac.h> | #include <linux/pxa168_eth.h> | #include <linux/qed/qed_eth_if.h> | #include <linux/qed/qed_fcoe_if.h> | #include <linux/qed/qed_if.h> | #include <linux/qed/qed_iov_if.h> | #include <linux/qed/qed_iscsi_if.h> | #include <linux/qed/qed_ll2_if.h> | #include <linux/qed/qed_nvmetcp_if.h> | #include <linux/qed/qed_rdma_if.h> | #include <linux/sfp.h> | #include <linux/sh_eth.h> | #include <linux/smsc911x.h> | #include <linux/soc/nxp/lpc32xx-misc.h> | #include <linux/stmmac.h> | #include <linux/sunrpc/svc_rdma.h> | #include <linux/sxgbe_platform.h> | #include <net/cfg80211.h> | #include <net/dsa.h> | #include <net/mac80211.h> | #include <net/selftests.h> | #include <rdma/ib_addr.h> | #include <rdma/ib_cache.h> | #include <rdma/ib_cm.h> | #include <rdma/ib_hdrs.h> | #include <rdma/ib_mad.h> | #include <rdma/ib_marshall.h> | #include <rdma/ib_pack.h> | #include <rdma/ib_pma.h> | #include <rdma/ib_sa.h> | #include <rdma/ib_smi.h> | #include <rdma/ib_umem.h> | #include <rdma/ib_umem_odp.h> | #include <rdma/ib_verbs.h> | #include <rdma/iw_cm.h> | #include <rdma/mr_pool.h> | #include <rdma/opa_addr.h> | #include <rdma/opa_port_info.h> | #include <rdma/opa_smi.h> | #include <rdma/opa_vnic.h> | #include <rdma/rdma_cm.h> | #include <rdma/rdma_cm_ib.h> | #include <rdma/rdmavt_cq.h> | #include <rdma/rdma_vt.h> | #include <rdma/rdmavt_qp.h> | #include <rdma/rw.h> | #include <rdma/tid_rdma_defs.h> | #include <rdma/uverbs_ioctl.h> | #include <rdma/uverbs_named_ioctl.h> | #include <rdma/uverbs_std_types.h> | #include <rdma/uverbs_types.h> | #include <soc/mscc/ocelot.h> | #include <soc/mscc/ocelot_ptp.h> | #include <soc/mscc/ocelot_vcap.h> | #include <trace/events/ib_mad.h> | #include <trace/events/rdma_core.h> | #include <trace/events/rdma.h> | #include <trace/events/rpcrdma.h> | #include <uapi/linux/ethtool.h> | #include <uapi/linux/ethtool_netlink.h> | #include <uapi/linux/mdio.h> | #include <uapi/linux/mii.h> ) @depends on i@ expression list args; @@ ( - bitmap_zero(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_zero(args) | - bitmap_copy(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_copy(args) | - bitmap_and(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_and(args) | - bitmap_or(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_or(args) | - bitmap_empty(args, ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_empty(args) | - bitmap_andnot(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_andnot(args) | - bitmap_equal(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_equal(args) | - bitmap_intersects(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_intersects(args) | - bitmap_subset(args, __ETHTOOL_LINK_MODE_MASK_NBITS) + linkmode_subset(args) ) Add missing linux/mii.h include to mellanox. -DaveM Signed-off-by: Sean Anderson <sean.anderson@seco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
209 lines
6.1 KiB
C
209 lines
6.1 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/* Microchip Sparx5 Switch driver
|
|
*
|
|
* Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/phylink.h>
|
|
#include <linux/device.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/sfp.h>
|
|
|
|
#include "sparx5_main_regs.h"
|
|
#include "sparx5_main.h"
|
|
#include "sparx5_port.h"
|
|
|
|
static bool port_conf_has_changed(struct sparx5_port_config *a, struct sparx5_port_config *b)
|
|
{
|
|
if (a->speed != b->speed ||
|
|
a->portmode != b->portmode ||
|
|
a->autoneg != b->autoneg ||
|
|
a->pause_adv != b->pause_adv ||
|
|
a->power_down != b->power_down ||
|
|
a->media != b->media)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static void sparx5_phylink_validate(struct phylink_config *config,
|
|
unsigned long *supported,
|
|
struct phylink_link_state *state)
|
|
{
|
|
struct sparx5_port *port = netdev_priv(to_net_dev(config->dev));
|
|
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
|
|
|
|
phylink_set(mask, Autoneg);
|
|
phylink_set_port_modes(mask);
|
|
phylink_set(mask, Pause);
|
|
phylink_set(mask, Asym_Pause);
|
|
|
|
switch (state->interface) {
|
|
case PHY_INTERFACE_MODE_5GBASER:
|
|
case PHY_INTERFACE_MODE_10GBASER:
|
|
case PHY_INTERFACE_MODE_25GBASER:
|
|
case PHY_INTERFACE_MODE_NA:
|
|
if (port->conf.bandwidth == SPEED_5000)
|
|
phylink_set(mask, 5000baseT_Full);
|
|
if (port->conf.bandwidth == SPEED_10000) {
|
|
phylink_set(mask, 5000baseT_Full);
|
|
phylink_set(mask, 10000baseT_Full);
|
|
phylink_set(mask, 10000baseCR_Full);
|
|
phylink_set(mask, 10000baseSR_Full);
|
|
phylink_set(mask, 10000baseLR_Full);
|
|
phylink_set(mask, 10000baseLRM_Full);
|
|
phylink_set(mask, 10000baseER_Full);
|
|
}
|
|
if (port->conf.bandwidth == SPEED_25000) {
|
|
phylink_set(mask, 5000baseT_Full);
|
|
phylink_set(mask, 10000baseT_Full);
|
|
phylink_set(mask, 10000baseCR_Full);
|
|
phylink_set(mask, 10000baseSR_Full);
|
|
phylink_set(mask, 10000baseLR_Full);
|
|
phylink_set(mask, 10000baseLRM_Full);
|
|
phylink_set(mask, 10000baseER_Full);
|
|
phylink_set(mask, 25000baseCR_Full);
|
|
phylink_set(mask, 25000baseSR_Full);
|
|
}
|
|
if (state->interface != PHY_INTERFACE_MODE_NA)
|
|
break;
|
|
fallthrough;
|
|
case PHY_INTERFACE_MODE_SGMII:
|
|
case PHY_INTERFACE_MODE_QSGMII:
|
|
phylink_set(mask, 10baseT_Half);
|
|
phylink_set(mask, 10baseT_Full);
|
|
phylink_set(mask, 100baseT_Half);
|
|
phylink_set(mask, 100baseT_Full);
|
|
phylink_set(mask, 1000baseT_Full);
|
|
phylink_set(mask, 1000baseX_Full);
|
|
if (state->interface != PHY_INTERFACE_MODE_NA)
|
|
break;
|
|
fallthrough;
|
|
case PHY_INTERFACE_MODE_1000BASEX:
|
|
case PHY_INTERFACE_MODE_2500BASEX:
|
|
if (state->interface != PHY_INTERFACE_MODE_2500BASEX) {
|
|
phylink_set(mask, 1000baseT_Full);
|
|
phylink_set(mask, 1000baseX_Full);
|
|
}
|
|
if (state->interface == PHY_INTERFACE_MODE_2500BASEX ||
|
|
state->interface == PHY_INTERFACE_MODE_NA) {
|
|
phylink_set(mask, 2500baseT_Full);
|
|
phylink_set(mask, 2500baseX_Full);
|
|
}
|
|
break;
|
|
default:
|
|
linkmode_zero(supported);
|
|
return;
|
|
}
|
|
linkmode_and(supported, supported, mask);
|
|
linkmode_and(state->advertising, state->advertising, mask);
|
|
}
|
|
|
|
static void sparx5_phylink_mac_config(struct phylink_config *config,
|
|
unsigned int mode,
|
|
const struct phylink_link_state *state)
|
|
{
|
|
/* Currently not used */
|
|
}
|
|
|
|
static void sparx5_phylink_mac_link_up(struct phylink_config *config,
|
|
struct phy_device *phy,
|
|
unsigned int mode,
|
|
phy_interface_t interface,
|
|
int speed, int duplex,
|
|
bool tx_pause, bool rx_pause)
|
|
{
|
|
struct sparx5_port *port = netdev_priv(to_net_dev(config->dev));
|
|
struct sparx5_port_config conf;
|
|
int err;
|
|
|
|
conf = port->conf;
|
|
conf.duplex = duplex;
|
|
conf.pause = 0;
|
|
conf.pause |= tx_pause ? MLO_PAUSE_TX : 0;
|
|
conf.pause |= rx_pause ? MLO_PAUSE_RX : 0;
|
|
conf.speed = speed;
|
|
/* Configure the port to speed/duplex/pause */
|
|
err = sparx5_port_config(port->sparx5, port, &conf);
|
|
if (err)
|
|
netdev_err(port->ndev, "port config failed: %d\n", err);
|
|
}
|
|
|
|
static void sparx5_phylink_mac_link_down(struct phylink_config *config,
|
|
unsigned int mode,
|
|
phy_interface_t interface)
|
|
{
|
|
/* Currently not used */
|
|
}
|
|
|
|
static struct sparx5_port *sparx5_pcs_to_port(struct phylink_pcs *pcs)
|
|
{
|
|
return container_of(pcs, struct sparx5_port, phylink_pcs);
|
|
}
|
|
|
|
static void sparx5_pcs_get_state(struct phylink_pcs *pcs,
|
|
struct phylink_link_state *state)
|
|
{
|
|
struct sparx5_port *port = sparx5_pcs_to_port(pcs);
|
|
struct sparx5_port_status status;
|
|
|
|
sparx5_get_port_status(port->sparx5, port, &status);
|
|
state->link = status.link && !status.link_down;
|
|
state->an_complete = status.an_complete;
|
|
state->speed = status.speed;
|
|
state->duplex = status.duplex;
|
|
state->pause = status.pause;
|
|
}
|
|
|
|
static int sparx5_pcs_config(struct phylink_pcs *pcs,
|
|
unsigned int mode,
|
|
phy_interface_t interface,
|
|
const unsigned long *advertising,
|
|
bool permit_pause_to_mac)
|
|
{
|
|
struct sparx5_port *port = sparx5_pcs_to_port(pcs);
|
|
struct sparx5_port_config conf;
|
|
int ret = 0;
|
|
|
|
conf = port->conf;
|
|
conf.power_down = false;
|
|
conf.portmode = interface;
|
|
conf.inband = phylink_autoneg_inband(mode);
|
|
conf.autoneg = phylink_test(advertising, Autoneg);
|
|
conf.pause_adv = 0;
|
|
if (phylink_test(advertising, Pause))
|
|
conf.pause_adv |= ADVERTISE_1000XPAUSE;
|
|
if (phylink_test(advertising, Asym_Pause))
|
|
conf.pause_adv |= ADVERTISE_1000XPSE_ASYM;
|
|
if (sparx5_is_baser(interface)) {
|
|
if (phylink_test(advertising, FIBRE))
|
|
conf.media = PHY_MEDIA_SR;
|
|
else
|
|
conf.media = PHY_MEDIA_DAC;
|
|
}
|
|
if (!port_conf_has_changed(&port->conf, &conf))
|
|
return ret;
|
|
/* Enable the PCS matching this interface type */
|
|
ret = sparx5_port_pcs_set(port->sparx5, port, &conf);
|
|
if (ret)
|
|
netdev_err(port->ndev, "port PCS config failed: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static void sparx5_pcs_aneg_restart(struct phylink_pcs *pcs)
|
|
{
|
|
/* Currently not used */
|
|
}
|
|
|
|
const struct phylink_pcs_ops sparx5_phylink_pcs_ops = {
|
|
.pcs_get_state = sparx5_pcs_get_state,
|
|
.pcs_config = sparx5_pcs_config,
|
|
.pcs_an_restart = sparx5_pcs_aneg_restart,
|
|
};
|
|
|
|
const struct phylink_mac_ops sparx5_phylink_mac_ops = {
|
|
.validate = sparx5_phylink_validate,
|
|
.mac_config = sparx5_phylink_mac_config,
|
|
.mac_link_down = sparx5_phylink_mac_link_down,
|
|
.mac_link_up = sparx5_phylink_mac_link_up,
|
|
};
|