Commit bf73478b authored by David S. Miller's avatar David S. Miller

Merge branch 'lan743x-phylink'

Raju Lakkaraju says:

====================
Add support to PHYLINK for LAN743x/PCI11x1x chips

This is the follow-up patch series of
https://lkml.iu.edu/hypermail/linux/kernel/2310.2/02078.html

Divide the PHYLINK adaptation and SFP modifications into two separate patch
series.

The current patch series focuses on transitioning the LAN743x driver's PHY
support from phylib to phylink.

Tested on PCI11010 Rev-1 Evaluation board

Change List:
============
V5 -> V6:
  - Remove the lan743x_find_max_speed( ) function. Not require
  - Add EEE enable check before calling lan743x_mac_eee_enable( ) function
V4 -> V5:
  - Remove the fixed_phy_unregister( ) function. Not require
  - Remove the "phydev->eee_enabled" check to update the MAC EEE
    enable/disable
  - Call lan743x_mac_eee_enable() with true after update tx_lpi_timer.
  - Add phy_support_eee() to initialize the EEE flags
V3 -> V4:
  - Add fixed-link patch along with this series.
    Note: Note: This code was developed by Mr.Russell King
    Ref:
    https://lore.kernel.org/netdev/LV8PR11MB8700C786F5F1C274C73036CC9F8E2@LV8PR11MB8700.namprd11.prod.outlook.com/T/#me943adf54f1ea082edf294aba448fa003a116815
  - Change phylink fixed-link function header's string from "Returns" to
    "Returns:"
  - Remove the EEE private variable from LAN743x adapter strcture and fix the
    EEE's set/get functions
  - set the individual caps (i.e. _RGMII, _RGMII_ID, _RGMII_RXID and
    __RGMII_TXID) replace with phy_interface_set_rgmii( ) function
  - Change lan743x_set_eee( ) to lan743x_mac_eee_enable( )

V2 -> V3:
  - Remove the unwanted parens in each of these if() sub-blocks
  - Replace "to_net_dev(config->dev)" with "netdev".
  - Add GMII_ID/RGMII_TXID/RGMII_RXID in supported_interfaces
  - Fix the lan743x_phy_handle_exists( ) return type

V1 -> V2:
  - Fix the Russell King's comments i.e. remove the speed, duplex update in
    lan743x_phylink_mac_config( )
  - pre-March 2020 legacy support has been removed

V0 -> V1:
  - Integrate with Synopsys DesignWare XPCS drivers
  - Based on external review comments,
  - Changes made to SGMII interface support only 1G/100M/10M bps speed
  - Changes made to 2500Base-X interface support only 2.5Gbps speed
  - Add check for not is_sgmii_en with is_sfp_support_en support
  - Change the "pci11x1x_strap_get_status" function return type from void to
    int
  - Add ethtool phylink wol, eee, pause get/set functions
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f3b6129b f95f28d7
...@@ -46,12 +46,13 @@ config LAN743X ...@@ -46,12 +46,13 @@ config LAN743X
tristate "LAN743x support" tristate "LAN743x support"
depends on PCI depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL depends on PTP_1588_CLOCK_OPTIONAL
select PHYLIB
select FIXED_PHY select FIXED_PHY
select CRC16 select CRC16
select CRC32 select CRC32
select PHYLINK
help help
Support for the Microchip LAN743x PCI Express Gigabit Ethernet chip Support for the Microchip LAN743x and PCI11x1x families of PCI
Express Ethernet devices
To compile this driver as a module, choose M here. The module will be To compile this driver as a module, choose M here. The module will be
called lan743x. called lan743x.
......
...@@ -1054,61 +1054,55 @@ static int lan743x_ethtool_get_eee(struct net_device *netdev, ...@@ -1054,61 +1054,55 @@ static int lan743x_ethtool_get_eee(struct net_device *netdev,
struct ethtool_keee *eee) struct ethtool_keee *eee)
{ {
struct lan743x_adapter *adapter = netdev_priv(netdev); struct lan743x_adapter *adapter = netdev_priv(netdev);
struct phy_device *phydev = netdev->phydev;
u32 buf;
int ret;
if (!phydev)
return -EIO;
if (!phydev->drv) {
netif_err(adapter, drv, adapter->netdev,
"Missing PHY Driver\n");
return -EIO;
}
ret = phy_ethtool_get_eee(phydev, eee); eee->tx_lpi_timer = lan743x_csr_read(adapter,
if (ret < 0) MAC_EEE_TX_LPI_REQ_DLY_CNT);
return ret;
buf = lan743x_csr_read(adapter, MAC_CR);
if (buf & MAC_CR_EEE_EN_) {
/* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */
buf = lan743x_csr_read(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT);
eee->tx_lpi_timer = buf;
} else {
eee->tx_lpi_timer = 0;
}
return 0; return phylink_ethtool_get_eee(adapter->phylink, eee);
} }
static int lan743x_ethtool_set_eee(struct net_device *netdev, static int lan743x_ethtool_set_eee(struct net_device *netdev,
struct ethtool_keee *eee) struct ethtool_keee *eee)
{ {
struct lan743x_adapter *adapter; struct lan743x_adapter *adapter = netdev_priv(netdev);
struct phy_device *phydev; u32 tx_lpi_timer;
u32 buf = 0;
if (!netdev) tx_lpi_timer = lan743x_csr_read(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT);
return -EINVAL; if (tx_lpi_timer != eee->tx_lpi_timer) {
adapter = netdev_priv(netdev); u32 mac_cr = lan743x_csr_read(adapter, MAC_CR);
if (!adapter)
return -EINVAL; /* Software should only change this field when Energy Efficient
phydev = netdev->phydev; * Ethernet Enable (EEEEN) is cleared.
if (!phydev) * This function will trigger an autonegotiation restart and
return -EIO; * eee will be reenabled during link up if eee was negotiated.
if (!phydev->drv) { */
netif_err(adapter, drv, adapter->netdev, lan743x_mac_eee_enable(adapter, false);
"Missing PHY Driver\n"); lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT,
return -EIO; eee->tx_lpi_timer);
}
if (eee->eee_enabled) { if (mac_cr & MAC_CR_EEE_EN_)
buf = (u32)eee->tx_lpi_timer; lan743x_mac_eee_enable(adapter, true);
lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT, buf);
} }
return phy_ethtool_set_eee(phydev, eee); return phylink_ethtool_set_eee(adapter->phylink, eee);
}
static int
lan743x_ethtool_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd)
{
struct lan743x_adapter *adapter = netdev_priv(netdev);
return phylink_ethtool_ksettings_set(adapter->phylink, cmd);
}
static int
lan743x_ethtool_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
struct lan743x_adapter *adapter = netdev_priv(netdev);
return phylink_ethtool_ksettings_get(adapter->phylink, cmd);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -1120,8 +1114,7 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev, ...@@ -1120,8 +1114,7 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev,
wol->supported = 0; wol->supported = 0;
wol->wolopts = 0; wol->wolopts = 0;
if (netdev->phydev) phylink_ethtool_get_wol(adapter->phylink, wol);
phy_ethtool_get_wol(netdev->phydev, wol);
if (wol->supported != adapter->phy_wol_supported) if (wol->supported != adapter->phy_wol_supported)
netif_warn(adapter, drv, adapter->netdev, netif_warn(adapter, drv, adapter->netdev,
...@@ -1162,7 +1155,7 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev, ...@@ -1162,7 +1155,7 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
!(adapter->phy_wol_supported & WAKE_MAGICSECURE)) !(adapter->phy_wol_supported & WAKE_MAGICSECURE))
phy_wol.wolopts &= ~WAKE_MAGIC; phy_wol.wolopts &= ~WAKE_MAGIC;
ret = phy_ethtool_set_wol(netdev->phydev, &phy_wol); ret = phylink_ethtool_set_wol(adapter->phylink, wol);
if (ret && (ret != -EOPNOTSUPP)) if (ret && (ret != -EOPNOTSUPP))
return ret; return ret;
...@@ -1351,44 +1344,16 @@ static void lan743x_get_pauseparam(struct net_device *dev, ...@@ -1351,44 +1344,16 @@ static void lan743x_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *pause) struct ethtool_pauseparam *pause)
{ {
struct lan743x_adapter *adapter = netdev_priv(dev); struct lan743x_adapter *adapter = netdev_priv(dev);
struct lan743x_phy *phy = &adapter->phy;
if (phy->fc_request_control & FLOW_CTRL_TX) phylink_ethtool_get_pauseparam(adapter->phylink, pause);
pause->tx_pause = 1;
if (phy->fc_request_control & FLOW_CTRL_RX)
pause->rx_pause = 1;
pause->autoneg = phy->fc_autoneg;
} }
static int lan743x_set_pauseparam(struct net_device *dev, static int lan743x_set_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *pause) struct ethtool_pauseparam *pause)
{ {
struct lan743x_adapter *adapter = netdev_priv(dev); struct lan743x_adapter *adapter = netdev_priv(dev);
struct phy_device *phydev = dev->phydev;
struct lan743x_phy *phy = &adapter->phy;
if (!phydev)
return -ENODEV;
if (!phy_validate_pause(phydev, pause))
return -EINVAL;
phy->fc_request_control = 0;
if (pause->rx_pause)
phy->fc_request_control |= FLOW_CTRL_RX;
if (pause->tx_pause) return phylink_ethtool_set_pauseparam(adapter->phylink, pause);
phy->fc_request_control |= FLOW_CTRL_TX;
phy->fc_autoneg = pause->autoneg;
if (pause->autoneg == AUTONEG_DISABLE)
lan743x_mac_flow_ctrl_set_enables(adapter, pause->tx_pause,
pause->rx_pause);
else
phy_set_asym_pause(phydev, pause->rx_pause, pause->tx_pause);
return 0;
} }
const struct ethtool_ops lan743x_ethtool_ops = { const struct ethtool_ops lan743x_ethtool_ops = {
...@@ -1413,8 +1378,8 @@ const struct ethtool_ops lan743x_ethtool_ops = { ...@@ -1413,8 +1378,8 @@ const struct ethtool_ops lan743x_ethtool_ops = {
.get_ts_info = lan743x_ethtool_get_ts_info, .get_ts_info = lan743x_ethtool_get_ts_info,
.get_eee = lan743x_ethtool_get_eee, .get_eee = lan743x_ethtool_get_eee,
.set_eee = lan743x_ethtool_set_eee, .set_eee = lan743x_ethtool_set_eee,
.get_link_ksettings = phy_ethtool_get_link_ksettings, .get_link_ksettings = lan743x_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings, .set_link_ksettings = lan743x_ethtool_set_link_ksettings,
.get_regs_len = lan743x_get_regs_len, .get_regs_len = lan743x_get_regs_len,
.get_regs = lan743x_get_regs, .get_regs = lan743x_get_regs,
.get_pauseparam = lan743x_get_pauseparam, .get_pauseparam = lan743x_get_pauseparam,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define _LAN743X_H #define _LAN743X_H
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/phylink.h>
#include "lan743x_ptp.h" #include "lan743x_ptp.h"
#define DRIVER_AUTHOR "Bryan Whitehead <Bryan.Whitehead@microchip.com>" #define DRIVER_AUTHOR "Bryan Whitehead <Bryan.Whitehead@microchip.com>"
...@@ -1083,6 +1084,8 @@ struct lan743x_adapter { ...@@ -1083,6 +1084,8 @@ struct lan743x_adapter {
u32 flags; u32 flags;
u32 hw_cfg; u32 hw_cfg;
phy_interface_t phy_interface; phy_interface_t phy_interface;
struct phylink *phylink;
struct phylink_config phylink_config;
}; };
#define LAN743X_COMPONENT_FLAG_RX(channel) BIT(20 + (channel)) #define LAN743X_COMPONENT_FLAG_RX(channel) BIT(20 + (channel))
...@@ -1203,5 +1206,6 @@ void lan743x_hs_syslock_release(struct lan743x_adapter *adapter); ...@@ -1203,5 +1206,6 @@ void lan743x_hs_syslock_release(struct lan743x_adapter *adapter);
void lan743x_mac_flow_ctrl_set_enables(struct lan743x_adapter *adapter, void lan743x_mac_flow_ctrl_set_enables(struct lan743x_adapter *adapter,
bool tx_enable, bool rx_enable); bool tx_enable, bool rx_enable);
int lan743x_sgmii_read(struct lan743x_adapter *adapter, u8 mmd, u16 addr); int lan743x_sgmii_read(struct lan743x_adapter *adapter, u8 mmd, u16 addr);
void lan743x_mac_eee_enable(struct lan743x_adapter *adapter, bool enable);
#endif /* _LAN743X_H */ #endif /* _LAN743X_H */
...@@ -1635,6 +1635,48 @@ static int phylink_register_sfp(struct phylink *pl, ...@@ -1635,6 +1635,48 @@ static int phylink_register_sfp(struct phylink *pl,
return ret; return ret;
} }
/**
* phylink_set_fixed_link() - set the fixed link
* @pl: a pointer to a &struct phylink returned from phylink_create()
* @state: a pointer to a struct phylink_link_state.
*
* This function is used when the link parameters are known and do not change,
* making it suitable for certain types of network connections.
*
* Returns: zero on success or negative error code.
*/
int phylink_set_fixed_link(struct phylink *pl,
const struct phylink_link_state *state)
{
const struct phy_setting *s;
unsigned long *adv;
if (pl->cfg_link_an_mode != MLO_AN_PHY || !state ||
!test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
return -EINVAL;
s = phy_lookup_setting(state->speed, state->duplex,
pl->supported, true);
if (!s)
return -EINVAL;
adv = pl->link_config.advertising;
linkmode_zero(adv);
linkmode_set_bit(s->bit, adv);
linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv);
pl->link_config.speed = state->speed;
pl->link_config.duplex = state->duplex;
pl->link_config.link = 1;
pl->link_config.an_complete = 1;
pl->cfg_link_an_mode = MLO_AN_FIXED;
pl->cur_link_an_mode = pl->cfg_link_an_mode;
return 0;
}
EXPORT_SYMBOL_GPL(phylink_set_fixed_link);
/** /**
* phylink_create() - create a phylink instance * phylink_create() - create a phylink instance
* @config: a pointer to the target &struct phylink_config * @config: a pointer to the target &struct phylink_config
......
...@@ -598,6 +598,8 @@ int phylink_fwnode_phy_connect(struct phylink *pl, ...@@ -598,6 +598,8 @@ int phylink_fwnode_phy_connect(struct phylink *pl,
const struct fwnode_handle *fwnode, const struct fwnode_handle *fwnode,
u32 flags); u32 flags);
void phylink_disconnect_phy(struct phylink *); void phylink_disconnect_phy(struct phylink *);
int phylink_set_fixed_link(struct phylink *,
const struct phylink_link_state *);
void phylink_mac_change(struct phylink *, bool up); void phylink_mac_change(struct phylink *, bool up);
void phylink_pcs_change(struct phylink_pcs *, bool up); void phylink_pcs_change(struct phylink_pcs *, bool up);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment