net: atlantic: A2: half duplex support
This patch adds support for 10M/100M/1G half duplex rates, which are supported by A2 in additional to full duplex rates supported by A1. Signed-off-by: Igor Russkikh <irusskikh@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
29cb9868fb
commit
071a02046c
@ -58,11 +58,14 @@
|
|||||||
#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)
|
||||||
|
|
||||||
#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_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,7 @@ 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct aq_stats_s {
|
struct aq_stats_s {
|
||||||
|
@ -939,8 +939,11 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|||||||
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 +964,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 +1003,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);
|
||||||
@ -1031,27 +1058,32 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|||||||
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:
|
||||||
|
@ -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)
|
||||||
|
@ -135,6 +135,10 @@ 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 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)
|
||||||
@ -202,6 +206,7 @@ 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;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user