net: atlantic: disable PTP on AQC111, AQC112

This patch disables PTP on AQC111 and AQC112 due to a known HW issue,
which can cause datapath issues.

Ideally PTP block should have been disabled via PHY provisioning, but
unfortunately many units have been shipped with enabled PTP block.
Thus, we have to work around this in the driver.

Fixes: dbcd6806af ("net: aquantia: add support for Phy access")
Signed-off-by: Nikita Danilov <ndanilov@marvell.com>
Signed-off-by: Mark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Nikita Danilov 2020-07-17 23:39:49 +03:00 committed by David S. Miller
parent 0b4a66a389
commit 23e500e887
7 changed files with 68 additions and 10 deletions

View File

@ -64,6 +64,7 @@ struct aq_hw_caps_s {
u8 rx_rings;
bool flow_control;
bool is_64_dma;
u32 quirks;
u32 priv_data_len;
};

View File

@ -415,6 +415,15 @@ int aq_nic_init(struct aq_nic_s *self)
self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) {
self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX;
err = aq_phy_init(self->aq_hw);
/* Disable the PTP on NICs where it's known to cause datapath
* problems.
* Ideally this should have been done by PHY provisioning, but
* many units have been shipped with enabled PTP block already.
*/
if (self->aq_nic_cfg.aq_hw_caps->quirks & AQ_NIC_QUIRK_BAD_PTP)
if (self->aq_hw->phy_id != HW_ATL_PHY_ID_MAX)
aq_phy_disable_ptp(self->aq_hw);
}
for (i = 0U; i < self->aq_vecs; i++) {

View File

@ -81,6 +81,8 @@ struct aq_nic_cfg_s {
#define AQ_NIC_FLAG_ERR_UNPLUG 0x40000000U
#define AQ_NIC_FLAG_ERR_HW 0x80000000U
#define AQ_NIC_QUIRK_BAD_PTP BIT(0)
#define AQ_NIC_WOL_MODES (WAKE_MAGIC |\
WAKE_PHY)

View File

@ -1,10 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-only
/* aQuantia Corporation Network Driver
* Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved
/* Atlantic Network Driver
*
* Copyright (C) 2018-2019 aQuantia Corporation
* Copyright (C) 2019-2020 Marvell International Ltd.
*/
#include "aq_phy.h"
#define HW_ATL_PTP_DISABLE_MSK BIT(10)
bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw)
{
int err = 0;
@ -145,3 +149,24 @@ bool aq_phy_init(struct aq_hw_s *aq_hw)
return true;
}
void aq_phy_disable_ptp(struct aq_hw_s *aq_hw)
{
static const u16 ptp_registers[] = {
0x031e,
0x031d,
0x031c,
0x031b,
};
u16 val;
int i;
for (i = 0; i < ARRAY_SIZE(ptp_registers); i++) {
val = aq_phy_read_reg(aq_hw, MDIO_MMD_VEND1,
ptp_registers[i]);
aq_phy_write_reg(aq_hw, MDIO_MMD_VEND1,
ptp_registers[i],
val & ~HW_ATL_PTP_DISABLE_MSK);
}
}

View File

@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* aQuantia Corporation Network Driver
* Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved
/* Atlantic Network Driver
*
* Copyright (C) 2018-2019 aQuantia Corporation
* Copyright (C) 2019-2020 Marvell International Ltd.
*/
#ifndef AQ_PHY_H
@ -29,4 +31,6 @@ bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw);
bool aq_phy_init(struct aq_hw_s *aq_hw);
void aq_phy_disable_ptp(struct aq_hw_s *aq_hw);
#endif /* AQ_PHY_H */

View File

@ -93,6 +93,25 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = {
AQ_NIC_RATE_100M,
};
const struct aq_hw_caps_s hw_atl_b0_caps_aqc111 = {
DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = AQ_NIC_RATE_5G |
AQ_NIC_RATE_2G5 |
AQ_NIC_RATE_1G |
AQ_NIC_RATE_100M,
.quirks = AQ_NIC_QUIRK_BAD_PTP,
};
const struct aq_hw_caps_s hw_atl_b0_caps_aqc112 = {
DEFAULT_B0_BOARD_BASIC_CAPABILITIES,
.media_type = AQ_HW_MEDIA_TYPE_TP,
.link_speed_msk = AQ_NIC_RATE_2G5 |
AQ_NIC_RATE_1G |
AQ_NIC_RATE_100M,
.quirks = AQ_NIC_QUIRK_BAD_PTP,
};
static int hw_atl_b0_hw_reset(struct aq_hw_s *self)
{
int err = 0;

View File

@ -18,17 +18,15 @@ extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc100;
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc107;
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc108;
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc109;
#define hw_atl_b0_caps_aqc111 hw_atl_b0_caps_aqc108
#define hw_atl_b0_caps_aqc112 hw_atl_b0_caps_aqc109
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc111;
extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc112;
#define hw_atl_b0_caps_aqc100s hw_atl_b0_caps_aqc100
#define hw_atl_b0_caps_aqc107s hw_atl_b0_caps_aqc107
#define hw_atl_b0_caps_aqc108s hw_atl_b0_caps_aqc108
#define hw_atl_b0_caps_aqc109s hw_atl_b0_caps_aqc109
#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc108
#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc109
#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc111
#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc112
extern const struct aq_hw_ops hw_atl_ops_b0;