Merge branch 'net-atlantic-additional-A2-features'
Igor Russkikh says: ==================== net: atlantic: additional A2 features This patchset adds more features to A2: * half duplex rates; * EEE; * flow control; * link partner capabilities reporting; * phy loopback. Feature-wise A2 is almost on-par with A1 save for WoL and filtering, which will be submitted as separate follow-up patchset(s). ==================== Reviewed-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8af7b4525a
|
@ -58,11 +58,19 @@
|
||||||
#define AQ_NIC_RATE_1G BIT(4)
|
#define AQ_NIC_RATE_1G BIT(4)
|
||||||
#define AQ_NIC_RATE_100M BIT(5)
|
#define AQ_NIC_RATE_100M BIT(5)
|
||||||
#define AQ_NIC_RATE_10M BIT(6)
|
#define AQ_NIC_RATE_10M BIT(6)
|
||||||
|
#define AQ_NIC_RATE_1G_HALF BIT(7)
|
||||||
|
#define AQ_NIC_RATE_100M_HALF BIT(8)
|
||||||
|
#define AQ_NIC_RATE_10M_HALF BIT(9)
|
||||||
|
|
||||||
#define AQ_NIC_RATE_EEE_10G BIT(7)
|
#define AQ_NIC_RATE_EEE_10G BIT(10)
|
||||||
#define AQ_NIC_RATE_EEE_5G BIT(8)
|
#define AQ_NIC_RATE_EEE_5G BIT(11)
|
||||||
#define AQ_NIC_RATE_EEE_2G5 BIT(9)
|
#define AQ_NIC_RATE_EEE_2G5 BIT(12)
|
||||||
#define AQ_NIC_RATE_EEE_1G BIT(10)
|
#define AQ_NIC_RATE_EEE_1G BIT(13)
|
||||||
#define AQ_NIC_RATE_EEE_100M BIT(11)
|
#define AQ_NIC_RATE_EEE_100M BIT(14)
|
||||||
|
#define AQ_NIC_RATE_EEE_MSK (AQ_NIC_RATE_EEE_10G |\
|
||||||
|
AQ_NIC_RATE_EEE_5G |\
|
||||||
|
AQ_NIC_RATE_EEE_2G5 |\
|
||||||
|
AQ_NIC_RATE_EEE_1G |\
|
||||||
|
AQ_NIC_RATE_EEE_100M)
|
||||||
|
|
||||||
#endif /* AQ_COMMON_H */
|
#endif /* AQ_COMMON_H */
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/* Atlantic Network Driver
|
||||||
* aQuantia Corporation Network Driver
|
*
|
||||||
* Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
|
* Copyright (C) 2014-2019 aQuantia Corporation
|
||||||
|
* Copyright (C) 2019-2020 Marvell International Ltd.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* File aq_ethtool.c: Definition of ethertool related functions. */
|
/* File aq_ethtool.c: Definition of ethertool related functions. */
|
||||||
|
@ -611,16 +612,13 @@ static int aq_ethtool_get_ts_info(struct net_device *ndev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
|
static u32 eee_mask_to_ethtool_mask(u32 speed)
|
||||||
{
|
{
|
||||||
u32 rate = 0;
|
u32 rate = 0;
|
||||||
|
|
||||||
if (speed & AQ_NIC_RATE_EEE_10G)
|
if (speed & AQ_NIC_RATE_EEE_10G)
|
||||||
rate |= SUPPORTED_10000baseT_Full;
|
rate |= SUPPORTED_10000baseT_Full;
|
||||||
|
|
||||||
if (speed & AQ_NIC_RATE_EEE_2G5)
|
|
||||||
rate |= SUPPORTED_2500baseX_Full;
|
|
||||||
|
|
||||||
if (speed & AQ_NIC_RATE_EEE_1G)
|
if (speed & AQ_NIC_RATE_EEE_1G)
|
||||||
rate |= SUPPORTED_1000baseT_Full;
|
rate |= SUPPORTED_1000baseT_Full;
|
||||||
|
|
||||||
|
@ -656,7 +654,7 @@ static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
|
||||||
eee->eee_enabled = !!eee->advertised;
|
eee->eee_enabled = !!eee->advertised;
|
||||||
|
|
||||||
eee->tx_lpi_enabled = eee->eee_enabled;
|
eee->tx_lpi_enabled = eee->eee_enabled;
|
||||||
if (eee->advertised & eee->lp_advertised)
|
if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK)
|
||||||
eee->eee_active = true;
|
eee->eee_active = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -838,6 +836,7 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
|
||||||
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
||||||
struct aq_nic_cfg_s *cfg;
|
struct aq_nic_cfg_s *cfg;
|
||||||
u32 priv_flags;
|
u32 priv_flags;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
cfg = aq_nic_get_cfg(aq_nic);
|
cfg = aq_nic_get_cfg(aq_nic);
|
||||||
priv_flags = cfg->priv_flags;
|
priv_flags = cfg->priv_flags;
|
||||||
|
@ -859,10 +858,10 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
|
||||||
dev_open(ndev, NULL);
|
dev_open(ndev, NULL);
|
||||||
}
|
}
|
||||||
} else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
|
} else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
|
||||||
aq_nic_set_loopback(aq_nic);
|
ret = aq_nic_set_loopback(aq_nic);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct ethtool_ops aq_ethtool_ops = {
|
const struct ethtool_ops aq_ethtool_ops = {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/* Atlantic Network Driver
|
||||||
* aQuantia Corporation Network Driver
|
*
|
||||||
* Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
|
* Copyright (C) 2014-2019 aQuantia Corporation
|
||||||
|
* Copyright (C) 2019-2020 Marvell International Ltd.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* File aq_hw.h: Declaration of abstract interface for NIC hardware specific
|
/* File aq_hw.h: Declaration of abstract interface for NIC hardware specific
|
||||||
|
@ -69,6 +70,9 @@ struct aq_hw_caps_s {
|
||||||
|
|
||||||
struct aq_hw_link_status_s {
|
struct aq_hw_link_status_s {
|
||||||
unsigned int mbps;
|
unsigned int mbps;
|
||||||
|
bool full_duplex;
|
||||||
|
u32 lp_link_speed_msk;
|
||||||
|
u32 lp_flow_control;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct aq_stats_s {
|
struct aq_stats_s {
|
||||||
|
|
|
@ -935,12 +935,17 @@ static void aq_nic_update_ndev_stats(struct aq_nic_s *self)
|
||||||
void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
||||||
struct ethtool_link_ksettings *cmd)
|
struct ethtool_link_ksettings *cmd)
|
||||||
{
|
{
|
||||||
|
u32 lp_link_speed_msk;
|
||||||
|
|
||||||
if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE)
|
if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE)
|
||||||
cmd->base.port = PORT_FIBRE;
|
cmd->base.port = PORT_FIBRE;
|
||||||
else
|
else
|
||||||
cmd->base.port = PORT_TP;
|
cmd->base.port = PORT_TP;
|
||||||
/* This driver supports only 10G capable adapters, so DUPLEX_FULL */
|
|
||||||
cmd->base.duplex = DUPLEX_FULL;
|
cmd->base.duplex = DUPLEX_UNKNOWN;
|
||||||
|
if (self->link_status.mbps)
|
||||||
|
cmd->base.duplex = self->link_status.full_duplex ?
|
||||||
|
DUPLEX_FULL : DUPLEX_HALF;
|
||||||
cmd->base.autoneg = self->aq_nic_cfg.is_autoneg;
|
cmd->base.autoneg = self->aq_nic_cfg.is_autoneg;
|
||||||
|
|
||||||
ethtool_link_ksettings_zero_link_mode(cmd, supported);
|
ethtool_link_ksettings_zero_link_mode(cmd, supported);
|
||||||
|
@ -961,14 +966,26 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
||||||
1000baseT_Full);
|
1000baseT_Full);
|
||||||
|
|
||||||
|
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_1G_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
||||||
|
1000baseT_Half);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M)
|
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
||||||
100baseT_Full);
|
100baseT_Full);
|
||||||
|
|
||||||
|
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
||||||
|
100baseT_Half);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M)
|
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
||||||
10baseT_Full);
|
10baseT_Full);
|
||||||
|
|
||||||
|
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
||||||
|
10baseT_Half);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.aq_hw_caps->flow_control) {
|
if (self->aq_nic_cfg.aq_hw_caps->flow_control) {
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
||||||
Pause);
|
Pause);
|
||||||
|
@ -988,30 +1005,42 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
||||||
if (self->aq_nic_cfg.is_autoneg)
|
if (self->aq_nic_cfg.is_autoneg)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
|
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10G)
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10G)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
10000baseT_Full);
|
10000baseT_Full);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_5G)
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_5G)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
5000baseT_Full);
|
5000baseT_Full);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5)
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
2500baseT_Full);
|
2500baseT_Full);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G)
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
1000baseT_Full);
|
1000baseT_Full);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M)
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
|
1000baseT_Half);
|
||||||
|
|
||||||
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
100baseT_Full);
|
100baseT_Full);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M)
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
|
100baseT_Half);
|
||||||
|
|
||||||
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
10baseT_Full);
|
10baseT_Full);
|
||||||
|
|
||||||
|
if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
|
10baseT_Half);
|
||||||
|
|
||||||
if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX)
|
if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX)
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||||
Pause);
|
Pause);
|
||||||
|
@ -1026,32 +1055,84 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
|
ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
|
||||||
else
|
else
|
||||||
ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
|
ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
|
||||||
|
|
||||||
|
ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
|
||||||
|
lp_link_speed_msk = self->aq_hw->aq_link_status.lp_link_speed_msk;
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_10G)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
10000baseT_Full);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_5G)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
5000baseT_Full);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_2G5)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
2500baseT_Full);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_1G)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
1000baseT_Full);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_1G_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
1000baseT_Half);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_100M)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
100baseT_Full);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_100M_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
100baseT_Half);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_10M)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
10baseT_Full);
|
||||||
|
|
||||||
|
if (lp_link_speed_msk & AQ_NIC_RATE_10M_HALF)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
10baseT_Half);
|
||||||
|
|
||||||
|
if (self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_RX)
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
Pause);
|
||||||
|
if (!!(self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_TX) ^
|
||||||
|
!!(self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_RX))
|
||||||
|
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
|
||||||
|
Asym_Pause);
|
||||||
}
|
}
|
||||||
|
|
||||||
int aq_nic_set_link_ksettings(struct aq_nic_s *self,
|
int aq_nic_set_link_ksettings(struct aq_nic_s *self,
|
||||||
const struct ethtool_link_ksettings *cmd)
|
const struct ethtool_link_ksettings *cmd)
|
||||||
{
|
{
|
||||||
u32 speed = 0U;
|
int fduplex = (cmd->base.duplex == DUPLEX_FULL);
|
||||||
|
u32 speed = cmd->base.speed;
|
||||||
u32 rate = 0U;
|
u32 rate = 0U;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
if (!fduplex && speed > SPEED_1000) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->base.autoneg == AUTONEG_ENABLE) {
|
if (cmd->base.autoneg == AUTONEG_ENABLE) {
|
||||||
rate = self->aq_nic_cfg.aq_hw_caps->link_speed_msk;
|
rate = self->aq_nic_cfg.aq_hw_caps->link_speed_msk;
|
||||||
self->aq_nic_cfg.is_autoneg = true;
|
self->aq_nic_cfg.is_autoneg = true;
|
||||||
} else {
|
} else {
|
||||||
speed = cmd->base.speed;
|
|
||||||
|
|
||||||
switch (speed) {
|
switch (speed) {
|
||||||
case SPEED_10:
|
case SPEED_10:
|
||||||
rate = AQ_NIC_RATE_10M;
|
rate = fduplex ? AQ_NIC_RATE_10M : AQ_NIC_RATE_10M_HALF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPEED_100:
|
case SPEED_100:
|
||||||
rate = AQ_NIC_RATE_100M;
|
rate = fduplex ? AQ_NIC_RATE_100M
|
||||||
|
: AQ_NIC_RATE_100M_HALF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPEED_1000:
|
case SPEED_1000:
|
||||||
rate = AQ_NIC_RATE_1G;
|
rate = fduplex ? AQ_NIC_RATE_1G : AQ_NIC_RATE_1G_HALF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPEED_2500:
|
case SPEED_2500:
|
||||||
|
|
|
@ -108,7 +108,7 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc)
|
int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc)
|
||||||
{
|
{
|
||||||
hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc);
|
hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc);
|
||||||
|
|
||||||
|
@ -1556,7 +1556,7 @@ static int hw_atl_b0_hw_vlan_ctrl(struct aq_hw_s *self, bool enable)
|
||||||
return aq_hw_err_from_flags(self);
|
return aq_hw_err_from_flags(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable)
|
int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case AQ_HW_LOOPBACK_DMA_SYS:
|
case AQ_HW_LOOPBACK_DMA_SYS:
|
||||||
|
|
|
@ -62,6 +62,9 @@ void hw_atl_b0_hw_init_rx_rss_ctrl1(struct aq_hw_s *self);
|
||||||
|
|
||||||
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr);
|
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr);
|
||||||
|
|
||||||
|
int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc);
|
||||||
|
int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable);
|
||||||
|
|
||||||
int hw_atl_b0_hw_start(struct aq_hw_s *self);
|
int hw_atl_b0_hw_start(struct aq_hw_s *self);
|
||||||
|
|
||||||
int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask);
|
int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask);
|
||||||
|
|
|
@ -704,6 +704,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
link_status->full_duplex = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,6 +274,7 @@ static int aq_fw2x_update_link_status(struct aq_hw_s *self)
|
||||||
} else {
|
} else {
|
||||||
link_status->mbps = 0;
|
link_status->mbps = 0;
|
||||||
}
|
}
|
||||||
|
link_status->full_duplex = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,11 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = {
|
||||||
AQ_NIC_RATE_5G |
|
AQ_NIC_RATE_5G |
|
||||||
AQ_NIC_RATE_2G5 |
|
AQ_NIC_RATE_2G5 |
|
||||||
AQ_NIC_RATE_1G |
|
AQ_NIC_RATE_1G |
|
||||||
|
AQ_NIC_RATE_1G_HALF |
|
||||||
AQ_NIC_RATE_100M |
|
AQ_NIC_RATE_100M |
|
||||||
AQ_NIC_RATE_10M,
|
AQ_NIC_RATE_100M_HALF |
|
||||||
|
AQ_NIC_RATE_10M |
|
||||||
|
AQ_NIC_RATE_10M_HALF,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self)
|
static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self)
|
||||||
|
@ -178,6 +181,8 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self)
|
||||||
|
|
||||||
threshold = (rx_buff_size * (1024U / 32U) * 50U) / 100U;
|
threshold = (rx_buff_size * (1024U / 32U) * 50U) / 100U;
|
||||||
hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, threshold, tc);
|
hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, threshold, tc);
|
||||||
|
|
||||||
|
hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* QoS 802.1p priority -> TC mapping */
|
/* QoS 802.1p priority -> TC mapping */
|
||||||
|
@ -838,4 +843,6 @@ const struct aq_hw_ops hw_atl2_ops = {
|
||||||
.hw_get_hw_stats = hw_atl2_utils_get_hw_stats,
|
.hw_get_hw_stats = hw_atl2_utils_get_hw_stats,
|
||||||
.hw_get_fw_version = hw_atl2_utils_get_fw_version,
|
.hw_get_fw_version = hw_atl2_utils_get_fw_version,
|
||||||
.hw_set_offload = hw_atl_b0_hw_offload_set,
|
.hw_set_offload = hw_atl_b0_hw_offload_set,
|
||||||
|
.hw_set_loopback = hw_atl_b0_set_loopback,
|
||||||
|
.hw_set_fc = hw_atl_b0_set_fc,
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "aq_hw.h"
|
#include "aq_hw.h"
|
||||||
#include "aq_hw_utils.h"
|
#include "aq_hw_utils.h"
|
||||||
|
#include "aq_nic.h"
|
||||||
#include "hw_atl/hw_atl_llh.h"
|
#include "hw_atl/hw_atl_llh.h"
|
||||||
#include "hw_atl2_utils.h"
|
#include "hw_atl2_utils.h"
|
||||||
#include "hw_atl2_llh.h"
|
#include "hw_atl2_llh.h"
|
||||||
|
@ -135,6 +136,67 @@ static void a2_link_speed_mask2fw(u32 speed,
|
||||||
link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G);
|
link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G);
|
||||||
link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M);
|
link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M);
|
||||||
link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M);
|
link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M);
|
||||||
|
|
||||||
|
link_options->rate_1G_hd = !!(speed & AQ_NIC_RATE_1G_HALF);
|
||||||
|
link_options->rate_100M_hd = !!(speed & AQ_NIC_RATE_100M_HALF);
|
||||||
|
link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 a2_fw_dev_to_eee_mask(struct device_link_caps_s *device_link_caps)
|
||||||
|
{
|
||||||
|
u32 rate = 0;
|
||||||
|
|
||||||
|
if (device_link_caps->eee_10G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_10G;
|
||||||
|
if (device_link_caps->eee_5G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_5G;
|
||||||
|
if (device_link_caps->eee_2P5G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_2G5;
|
||||||
|
if (device_link_caps->eee_1G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_1G;
|
||||||
|
if (device_link_caps->eee_100M)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_100M;
|
||||||
|
|
||||||
|
return rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps)
|
||||||
|
{
|
||||||
|
u32 rate = 0;
|
||||||
|
|
||||||
|
if (lkp_link_caps->rate_10G)
|
||||||
|
rate |= AQ_NIC_RATE_10G;
|
||||||
|
if (lkp_link_caps->rate_5G)
|
||||||
|
rate |= AQ_NIC_RATE_5G;
|
||||||
|
if (lkp_link_caps->rate_N5G)
|
||||||
|
rate |= AQ_NIC_RATE_5GSR;
|
||||||
|
if (lkp_link_caps->rate_2P5G)
|
||||||
|
rate |= AQ_NIC_RATE_2G5;
|
||||||
|
if (lkp_link_caps->rate_1G)
|
||||||
|
rate |= AQ_NIC_RATE_1G;
|
||||||
|
if (lkp_link_caps->rate_1G_hd)
|
||||||
|
rate |= AQ_NIC_RATE_1G_HALF;
|
||||||
|
if (lkp_link_caps->rate_100M)
|
||||||
|
rate |= AQ_NIC_RATE_100M;
|
||||||
|
if (lkp_link_caps->rate_100M_hd)
|
||||||
|
rate |= AQ_NIC_RATE_100M_HALF;
|
||||||
|
if (lkp_link_caps->rate_10M)
|
||||||
|
rate |= AQ_NIC_RATE_10M;
|
||||||
|
if (lkp_link_caps->rate_10M_hd)
|
||||||
|
rate |= AQ_NIC_RATE_10M_HALF;
|
||||||
|
|
||||||
|
if (lkp_link_caps->eee_10G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_10G;
|
||||||
|
if (lkp_link_caps->eee_5G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_5G;
|
||||||
|
if (lkp_link_caps->eee_2P5G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_2G5;
|
||||||
|
if (lkp_link_caps->eee_1G)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_1G;
|
||||||
|
if (lkp_link_caps->eee_100M)
|
||||||
|
rate |= AQ_NIC_RATE_EEE_100M;
|
||||||
|
|
||||||
|
return rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
|
static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
|
||||||
|
@ -149,6 +211,26 @@ static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
|
||||||
return hw_atl2_shared_buffer_finish_ack(self);
|
return hw_atl2_shared_buffer_finish_ack(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void aq_a2_fw_set_mpi_flow_control(struct aq_hw_s *self,
|
||||||
|
struct link_options_s *link_options)
|
||||||
|
{
|
||||||
|
u32 flow_control = self->aq_nic_cfg->fc.req;
|
||||||
|
|
||||||
|
link_options->pause_rx = !!(flow_control & AQ_NIC_FC_RX);
|
||||||
|
link_options->pause_tx = !!(flow_control & AQ_NIC_FC_TX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s *self,
|
||||||
|
struct link_options_s *link_options,
|
||||||
|
u32 eee_speeds)
|
||||||
|
{
|
||||||
|
link_options->eee_10G = !!(eee_speeds & AQ_NIC_RATE_EEE_10G);
|
||||||
|
link_options->eee_5G = !!(eee_speeds & AQ_NIC_RATE_EEE_5G);
|
||||||
|
link_options->eee_2P5G = !!(eee_speeds & AQ_NIC_RATE_EEE_2G5);
|
||||||
|
link_options->eee_1G = !!(eee_speeds & AQ_NIC_RATE_EEE_1G);
|
||||||
|
link_options->eee_100M = !!(eee_speeds & AQ_NIC_RATE_EEE_100M);
|
||||||
|
}
|
||||||
|
|
||||||
static int aq_a2_fw_set_state(struct aq_hw_s *self,
|
static int aq_a2_fw_set_state(struct aq_hw_s *self,
|
||||||
enum hal_atl_utils_fw_state_e state)
|
enum hal_atl_utils_fw_state_e state)
|
||||||
{
|
{
|
||||||
|
@ -159,6 +241,9 @@ static int aq_a2_fw_set_state(struct aq_hw_s *self,
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case MPI_INIT:
|
case MPI_INIT:
|
||||||
link_options.link_up = 1U;
|
link_options.link_up = 1U;
|
||||||
|
aq_a2_fw_upd_eee_rate_bits(self, &link_options,
|
||||||
|
self->aq_nic_cfg->eee_speeds);
|
||||||
|
aq_a2_fw_set_mpi_flow_control(self, &link_options);
|
||||||
break;
|
break;
|
||||||
case MPI_DEINIT:
|
case MPI_DEINIT:
|
||||||
link_options.link_up = 0U;
|
link_options.link_up = 0U;
|
||||||
|
@ -176,6 +261,7 @@ static int aq_a2_fw_set_state(struct aq_hw_s *self,
|
||||||
|
|
||||||
static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
|
static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
|
||||||
{
|
{
|
||||||
|
struct lkp_link_caps_s lkp_link_caps;
|
||||||
struct link_status_s link_status;
|
struct link_status_s link_status;
|
||||||
|
|
||||||
hw_atl2_shared_buffer_read(self, link_status, link_status);
|
hw_atl2_shared_buffer_read(self, link_status, link_status);
|
||||||
|
@ -202,6 +288,15 @@ static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
|
||||||
default:
|
default:
|
||||||
self->aq_link_status.mbps = 0;
|
self->aq_link_status.mbps = 0;
|
||||||
}
|
}
|
||||||
|
self->aq_link_status.full_duplex = link_status.duplex;
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
|
||||||
|
|
||||||
|
self->aq_link_status.lp_link_speed_msk =
|
||||||
|
a2_fw_lkp_to_mask(&lkp_link_caps);
|
||||||
|
self->aq_link_status.lp_flow_control =
|
||||||
|
((lkp_link_caps.pause_rx) ? AQ_NIC_FC_RX : 0) |
|
||||||
|
((lkp_link_caps.pause_tx) ? AQ_NIC_FC_TX : 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -260,6 +355,34 @@ static int aq_a2_fw_update_stats(struct aq_hw_s *self)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed)
|
||||||
|
{
|
||||||
|
struct link_options_s link_options;
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_get(self, link_options, link_options);
|
||||||
|
|
||||||
|
aq_a2_fw_upd_eee_rate_bits(self, &link_options, speed);
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_write(self, link_options, link_options);
|
||||||
|
|
||||||
|
return hw_atl2_shared_buffer_finish_ack(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int aq_a2_fw_get_eee_rate(struct aq_hw_s *self, u32 *rate,
|
||||||
|
u32 *supported_rates)
|
||||||
|
{
|
||||||
|
struct device_link_caps_s device_link_caps;
|
||||||
|
struct lkp_link_caps_s lkp_link_caps;
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_read(self, device_link_caps, device_link_caps);
|
||||||
|
hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
|
||||||
|
|
||||||
|
*supported_rates = a2_fw_dev_to_eee_mask(&device_link_caps);
|
||||||
|
*rate = a2_fw_lkp_to_mask(&lkp_link_caps);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
|
static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
|
||||||
{
|
{
|
||||||
struct link_options_s link_options;
|
struct link_options_s link_options;
|
||||||
|
@ -280,6 +403,52 @@ static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int aq_a2_fw_set_flow_control(struct aq_hw_s *self)
|
||||||
|
{
|
||||||
|
struct link_options_s link_options;
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_get(self, link_options, link_options);
|
||||||
|
|
||||||
|
aq_a2_fw_set_mpi_flow_control(self, &link_options);
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_write(self, link_options, link_options);
|
||||||
|
|
||||||
|
return hw_atl2_shared_buffer_finish_ack(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 aq_a2_fw_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
|
||||||
|
{
|
||||||
|
struct link_status_s link_status;
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_read(self, link_status, link_status);
|
||||||
|
|
||||||
|
*fcmode = ((link_status.pause_rx) ? AQ_NIC_FC_RX : 0) |
|
||||||
|
((link_status.pause_tx) ? AQ_NIC_FC_TX : 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int aq_a2_fw_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable)
|
||||||
|
{
|
||||||
|
struct link_options_s link_options;
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_get(self, link_options, link_options);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case AQ_HW_LOOPBACK_PHYINT_SYS:
|
||||||
|
link_options.internal_loopback = enable;
|
||||||
|
break;
|
||||||
|
case AQ_HW_LOOPBACK_PHYEXT_SYS:
|
||||||
|
link_options.external_loopback = enable;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_atl2_shared_buffer_write(self, link_options, link_options);
|
||||||
|
|
||||||
|
return hw_atl2_shared_buffer_finish_ack(self);
|
||||||
|
}
|
||||||
|
|
||||||
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
|
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
|
||||||
{
|
{
|
||||||
struct version_s version;
|
struct version_s version;
|
||||||
|
@ -317,4 +486,9 @@ const struct aq_fw_ops aq_a2_fw_ops = {
|
||||||
.set_state = aq_a2_fw_set_state,
|
.set_state = aq_a2_fw_set_state,
|
||||||
.update_link_status = aq_a2_fw_update_link_status,
|
.update_link_status = aq_a2_fw_update_link_status,
|
||||||
.update_stats = aq_a2_fw_update_stats,
|
.update_stats = aq_a2_fw_update_stats,
|
||||||
|
.set_eee_rate = aq_a2_fw_set_eee_rate,
|
||||||
|
.get_eee_rate = aq_a2_fw_get_eee_rate,
|
||||||
|
.set_flow_control = aq_a2_fw_set_flow_control,
|
||||||
|
.get_flow_control = aq_a2_fw_get_flow_control,
|
||||||
|
.set_phyloopback = aq_a2_fw_set_phyloopback,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue