From 4f2388d727c1a78c1f65f22a8ba12aa0d515a324 Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Mon, 28 Sep 2020 17:40:31 +0300 Subject: [PATCH 1/4] atlantic forwarding driver v1.1.12 [ATLDRV-1573] - Crash on enable EEE [ATLDRV-1576] - FWD: Add support of Antigua B0 statistics [ATLDRV-1577] - Add Downshift feature. Change-Id: I4b262076969bf0a6a6996fbf54e2e7e86fddee0b Signed-off-by: Dmitry Bogdanov Git-commit: dcb78b53f88c87405e81e1733592a721cfd75936 Git-repo: https://github.com/aquantia/linux-4.14-atlantic-forwarding Signed-off-by: Lakshit Tyagi --- .../ethernet/aquantia/atlantic-fwd/atl2_fw.c | 30 +++-- .../ethernet/aquantia/atlantic-fwd/atl2_fw.h | 37 +++++- .../aquantia/atlantic-fwd/atl_common.h | 7 +- .../aquantia/atlantic-fwd/atl_compat.h | 15 +++ .../aquantia/atlantic-fwd/atl_ethtool.c | 33 ++++- .../ethernet/aquantia/atlantic-fwd/atl_fw.c | 31 ++++- .../ethernet/aquantia/atlantic-fwd/atl_fw.h | 3 + .../ethernet/aquantia/atlantic-fwd/atl_hw.c | 116 ++++++++++++++---- .../ethernet/aquantia/atlantic-fwd/atl_main.c | 5 + .../ethernet/aquantia/atlantic-fwd/atl_regs.h | 18 +++ .../aquantia/atlantic-fwd/release_notes.txt | 6 + 11 files changed, 254 insertions(+), 47 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c index a5f0ca04bb09..17a1bcef2f41 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c @@ -214,7 +214,7 @@ static int __atl2_fw_wait_init(struct atl_hw *hw) "pauseQuanta invalid size"); BUILD_BUG_ON_MSG(sizeof(struct cable_diag_control_s) != 0x4, "cableDiagControl invalid size"); - BUILD_BUG_ON_MSG(sizeof(struct statistics_s) != 0x70, + BUILD_BUG_ON_MSG(sizeof(struct statistics_s) != 0x74, "statistics_s invalid size"); @@ -901,19 +901,34 @@ static int atl2_fw_set_mediadetect(struct atl_hw *hw, bool on) return atl2_shared_buffer_finish_ack(hw); } +static int atl2_fw_set_downshift(struct atl_hw *hw, bool on) +{ + struct link_options_s link_options; + + atl2_shared_buffer_get(hw, link_options, link_options); + + link_options.downshift = on; + + atl2_shared_buffer_write(hw, link_options, link_options); + + return atl2_shared_buffer_finish_ack(hw); +} + static int atl2_fw_unsupported(struct atl_hw *hw) { return -EOPNOTSUPP; } -int atl2_get_fw_version(struct atl_hw *hw, u32 *fw_version) +int atl2_get_fw_version(struct atl_hw *hw) { - struct mac_version_t mac_version; + struct atl_mcp *mcp = &hw->mcp; + struct version_s version; - atl2_shared_buffer_read(hw, version.mac, mac_version); - *fw_version = mac_version.major << 24 | mac_version.minor << 16 | - mac_version.build; + atl2_shared_buffer_read_safe(hw, version, &version); + mcp->fw_rev = version.mac.major << 24 | version.mac.minor << 16 | + version.mac.build; + mcp->interface_ver = version.drv_iface_ver; return 0; } @@ -927,6 +942,7 @@ static struct atl_fw_ops atl2_fw_ops = { .set_default_link = atl2_fw_set_default_link, .get_phy_temperature = atl2_fw_get_phy_temperature, .set_mediadetect = atl2_fw_set_mediadetect, + .set_downshift = atl2_fw_set_downshift, .send_macsec_req = (void *)atl2_fw_unsupported, .set_pad_stripping = atl2_fw_set_pad_stripping, .get_mac_addr = atl2_fw_get_mac_addr, @@ -943,7 +959,7 @@ int atl2_fw_init(struct atl_hw *hw) struct atl_mcp *mcp = &hw->mcp; int ret; - atl2_get_fw_version(hw, &mcp->fw_rev); + atl2_get_fw_version(hw); mcp->ops = &atl2_fw_ops; atl_dev_dbg("Detect ATL2FW %x\n", mcp->fw_rev); diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.h index 5db61f37253f..177251f536d8 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.h @@ -239,7 +239,8 @@ struct version_s { uint32_t minor:8; uint32_t build:16; } phy; - uint32_t rsvd:32; + uint32_t drv_iface_ver:4; + uint32_t rsvd:28; }; struct link_status_s { @@ -444,7 +445,7 @@ struct phy_fw_load_status_s { uint32_t rsvd2:2; }; -struct statistics_s { +struct statistics_a0_s { struct { uint32_t link_up; uint32_t link_down; @@ -477,6 +478,33 @@ struct statistics_s { uint32_t reserve_fw_gap; }; +struct statistics_b0_s { + uint64_t rx_good_octets; + uint64_t rx_pause_frames; + uint64_t rx_good_frames; + uint64_t rx_errors; + uint64_t rx_unicast_frames; + uint64_t rx_multicast_frames; + uint64_t rx_broadcast_frames; + + uint64_t tx_good_octets; + uint64_t tx_pause_frames; + uint64_t tx_good_frames; + uint64_t tx_errors; + uint64_t tx_unicast_frames; + uint64_t tx_multicast_frames; + uint64_t tx_broadcast_frames; + + uint32_t main_loop_cycles; +}; + +struct statistics_s { + union { + struct statistics_a0_s a0; + struct statistics_b0_s b0; + }; +}; + struct filter_caps_s { uint8_t l2_filters_base_index:6; uint8_t flexible_filter_mask:2; @@ -590,7 +618,6 @@ struct fw_interface_out { struct core_dump_s core_dump; uint32_t rsvd11:32; struct statistics_s stats; - uint32_t rsvd12:32; struct filter_caps_s filter_caps; struct device_caps_s device_caps; uint32_t rsvd13:32; @@ -627,6 +654,9 @@ struct fw_iti_hdr { #define ATL2_HOST_MODE_LOW_POWER 3 #define ATL2_HOST_MODE_SHUTDOWN 4 +#define ATL2_FW_INTERFACE_A0 0 +#define ATL2_FW_INTERFACE_B0 1 + #define ATL2_FW_CABLE_STATUS_OPEN_CIRCUIT 7 #define ATL2_FW_CABLE_STATUS_HIGH_MISMATCH 6 #define ATL2_FW_CABLE_STATUS_LOW_MISMATCH 5 @@ -683,7 +713,6 @@ enum ATL2_WAKE_REASON { }; int atl2_fw_init(struct atl_hw *hw); -int atl2_get_fw_version(struct atl_hw *hw, u32 *fw_version); int atl2_fw_set_filter_policy(struct atl_hw *hw, bool promisc, bool allmulti); diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h index 85643c61983a..df90dcaa6f6c 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h @@ -20,7 +20,7 @@ #include #include -#define ATL_VERSION "1.1.11" +#define ATL_VERSION "1.1.12" struct atl_nic; @@ -315,6 +315,7 @@ enum atl_priv_flags { ATL_PF_STATS_RESET, ATL_PF_STRIP_PAD, ATL_PF_MEDIA_DETECT, + ATL_PF_DOWNSHIFT, }; enum atl_priv_flag_bits { @@ -339,9 +340,11 @@ enum atl_priv_flag_bits { ATL_DEF_PF_BIT(STRIP_PAD), ATL_DEF_PF_BIT(MEDIA_DETECT), + ATL_DEF_PF_BIT(DOWNSHIFT), ATL_PF_RW_MASK = ATL_PF_LPB_MASK | ATL_PF_BIT(STATS_RESET) | - ATL_PF_BIT(STRIP_PAD) | ATL_PF_BIT(MEDIA_DETECT), + ATL_PF_BIT(STRIP_PAD) | ATL_PF_BIT(MEDIA_DETECT) | + ATL_PF_BIT(DOWNSHIFT), ATL_PF_RO_MASK = ATL_PF_LPI_MASK, }; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_compat.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_compat.h index b17e7f42e7c3..7bfbe9ef3860 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_compat.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_compat.h @@ -47,6 +47,21 @@ /* introduced in commit 72bb68721f80a1441e871b6afc9ab0b3793d5031 */ #define ATL_HAVE_IPV6_NTUPLE +#if RHEL_RELEASE_CODE == RHEL_RELEASE_VERSION(7, 3) +static inline void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, + u32 legacy_u32) +{ + bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); + dst[0] = legacy_u32; +} +#endif +#else +#define __ETHTOOL_DECLARE_LINK_MODE_MASK(VAR) unsigned long VAR[1] +static inline void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, + u32 legacy_u32) +{ + dst[0] = legacy_u32; +} #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) || RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3) diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c index d845bd8f9dc7..a55720b10dfe 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c @@ -181,6 +181,7 @@ static int atl_set_fixed_speed(struct atl_hw *hw, unsigned int speed, { unsigned int dplx = (duplex == DUPLEX_HALF) ? DUPLEX_HALF : DUPLEX_FULL; struct atl_link_state *lstate = &hw->link_state; + __ETHTOOL_DECLARE_LINK_MODE_MASK(link_modes); struct atl_link_type *type; unsigned long tmp; int i; @@ -197,9 +198,9 @@ static int atl_set_fixed_speed(struct atl_hw *hw, unsigned int speed, if (lstate->eee_enabled) { atl_link_to_kernel(lstate->supported >> ATL_EEE_BIT_OFFT, - &tmp, false); + link_modes, false); /* advertize the supported links */ - tmp = atl_kernel_to_link(&tmp, false); + tmp = atl_kernel_to_link(link_modes, false); lstate->advertized |= tmp << ATL_EEE_BIT_OFFT; } @@ -479,6 +480,7 @@ static int atl_set_eee(struct net_device *ndev, struct ethtool_eee *eee) struct atl_nic *nic = netdev_priv(ndev); struct atl_hw *hw = &nic->hw; struct atl_link_state *lstate = &hw->link_state; + __ETHTOOL_DECLARE_LINK_MODE_MASK(link_modes); unsigned long tmp = 0; if ((hw->chip_id == ATL_ATLANTIC) && (atl_fw_major(hw) < 2)) @@ -491,14 +493,15 @@ static int atl_set_eee(struct net_device *ndev, struct ethtool_eee *eee) if (lstate->eee_enabled) { atl_link_to_kernel(lstate->supported >> ATL_EEE_BIT_OFFT, - &tmp, false); - if (eee->advertised & ~tmp) + link_modes, false); + if (eee->advertised & ~link_modes[0]) return -EINVAL; /* advertize the requested link or all supported */ if (eee->advertised) - tmp = eee->advertised; - tmp = atl_kernel_to_link(&tmp, false); + ethtool_convert_legacy_u32_to_link_mode(link_modes, + eee->advertised); + tmp = atl_kernel_to_link(link_modes, false); } lstate->advertized &= ~ATL_EEE_MASK; @@ -655,6 +658,7 @@ static const char atl_priv_flags[][ETH_GSTRING_LEN] = { ATL_PRIV_FLAG(ResetStatistics, STATS_RESET), ATL_PRIV_FLAG(StripEtherPadding, STRIP_PAD), ATL_PRIV_FLAG(MediaDetect, MEDIA_DETECT), + ATL_PRIV_FLAG(Downshift, DOWNSHIFT), }; #if IS_ENABLED(CONFIG_MACSEC) && defined(NETIF_F_HW_MACSEC) @@ -1089,6 +1093,16 @@ int atl_set_media_detect(struct atl_nic *nic, bool on) return ret; } +int atl_set_downshift(struct atl_nic *nic, bool on) +{ + struct atl_hw *hw = &nic->hw; + int ret; + + ret = hw->mcp.ops->set_downshift(hw, on); + + return ret; +} + static uint32_t atl_get_priv_flags(struct net_device *ndev) { struct atl_nic *nic = netdev_priv(ndev); @@ -1129,6 +1143,13 @@ static int atl_set_priv_flags(struct net_device *ndev, uint32_t flags) return ret; } + if (diff & ATL_PF_BIT(DOWNSHIFT)) { + ret = atl_set_downshift(nic, + !!(flags & ATL_PF_BIT(DOWNSHIFT))); + if (ret) + return ret; + } + if (hweight32(lpb) > 1) { atl_nic_err("Can't enable more than one loopback simultaneously\n"); return -EINVAL; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.c index 8f90745a6f49..cafd661c4dd8 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.c @@ -655,6 +655,33 @@ unlock: return ret; } +static int atl_fw2_set_downshift(struct atl_hw *hw, bool on) +{ + uint32_t req; + int res = 0; + int ret = 0; + + atl_lock_fw(hw); + + if (on) + hw->mcp.req_high |= atl_fw2_downshift; + else + hw->mcp.req_high &= ~atl_fw2_downshift; + req = hw->mcp.req_high; + atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), req); + + busy_wait(10000, udelay(10), res, + atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_RES_HIGH)), + ((res ^ req) & atl_fw2_downshift) != 0); + if (((res ^ req) & atl_fw2_downshift) != 0) { + atl_dev_err("Timeout waiting for statistics\n"); + ret = -EIO; + } + + atl_unlock_fw(hw); + return ret; +} + static int __atl_fw2x_apply_msm_settings(struct atl_hw *hw) { @@ -982,7 +1009,8 @@ static struct atl_fw_ops atl_fw_ops[2] = { .dump_cfg = atl_fw1_unsupported, .restore_cfg = atl_fw1_unsupported, .set_phy_loopback = (void *)atl_fw1_unsupported, - .set_mediadetect = (void *)atl_fw1_unsupported, + .set_mediadetect = (void *)atl_fw1_unsupported, + .set_downshift = (void *)atl_fw1_unsupported, .send_macsec_req = (void *)atl_fw1_unsupported, .set_pad_stripping = (void *)atl_fw1_unsupported, .__get_hbeat = (void *)atl_fw1_unsupported, @@ -1003,6 +1031,7 @@ static struct atl_fw_ops atl_fw_ops[2] = { .restore_cfg = atl_fw2_restore_cfg, .set_phy_loopback = atl_fw2_set_phy_loopback, .set_mediadetect = atl_fw2_set_mediadetect, + .set_downshift = atl_fw2_set_downshift, .send_macsec_req = atl_fw2_send_macsec_request, .set_pad_stripping = atl_fw2_set_pad_stripping, .__get_hbeat = __atl_fw2_get_hbeat, diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.h index 9115933157ff..bea4b5483b2c 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.h @@ -31,6 +31,7 @@ struct atl_mcp { uint32_t caps_low; uint32_t caps_high; uint32_t caps_ex; + uint32_t interface_ver; struct mutex lock; unsigned long next_wdog; bool wdog_disabled; @@ -86,6 +87,7 @@ enum atl_fw2_opts { atl_define_bit(atl_fw2_wake_on_link, 16) atl_define_bit(atl_fw2_wake_on_link_force, 17) atl_define_bit(atl_fw2_phy_temp, 18) + atl_define_bit(atl_fw2_downshift, 19) atl_define_bit(atl_fw2_set_thermal, 21) atl_define_bit(atl_fw2_link_drop, 22) atl_define_bit(atl_fw2_nic_proxy, 0x17) @@ -287,6 +289,7 @@ struct atl_fw_ops { int (*restore_cfg)(struct atl_hw *hw); int (*set_phy_loopback)(struct atl_nic *nic, u32 mode); int (*set_mediadetect)(struct atl_hw *hw, bool on); + int (*set_downshift)(struct atl_hw *hw, bool on); int (*set_pad_stripping)(struct atl_hw *hw, bool on); int (*send_macsec_req)(struct atl_hw *hw, struct macsec_msg_fw_request *msg, diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c index da6fe59f363a..69aba92c4008 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c @@ -1242,6 +1242,91 @@ void atl_adjust_eth_stats(struct atl_ether_stats *stats, _stats[i] += add ? _base[i] : - _base[i]; } +static int __atl_fetch_msm1_stats(struct atl_hw *hw, + struct atl_ether_stats *stats) +{ + u32 reg, reg2; + int ret; + + ret = atl_hwsem_get(hw, ATL_MCP_SEM_MSM); + if (ret) + return ret; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PAUSE, ®, hwsem_put); + stats->tx_pause = reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PAUSE, ®, hwsem_put); + stats->rx_pause = reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_HI, ®2, hwsem_put); + stats->rx_ether_octets = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PKTS_GOOD, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ERRS, ®2, hwsem_put); + stats->rx_ether_pkts = reg + reg2; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_BROADCAST, ®, hwsem_put); + stats->rx_ether_broacasts = reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_MULTICAST, ®, hwsem_put); + stats->rx_ether_multicasts = reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_FCS_ERRS, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ALIGN_ERRS, ®2, hwsem_put); + stats->rx_ether_crc_align_errs = reg + reg2; + +hwsem_put: + atl_hwsem_put(hw, ATL_MCP_SEM_MSM); + return ret; +} + +static int __atl_fetch_msm2_stats(struct atl_hw *hw, + struct atl_ether_stats *stats) +{ + u32 reg, reg2; + int ret; + + ret = atl_hwsem_get(hw, ATL_MCP_SEM_MSM); + if (ret) + return ret; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PAUSE_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PAUSE_HI, ®2, hwsem_put); + stats->tx_pause = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_HI, ®2, hwsem_put); + stats->rx_pause = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_OCTETS_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_OCTETS_HI, ®2, hwsem_put); + stats->rx_ether_octets = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PKTS_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PKTS_HI, ®2, hwsem_put); + stats->rx_ether_pkts = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_BROADCAST_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_BROADCAST_HI, ®2, hwsem_put); + stats->rx_ether_broacasts = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_MULTICAST_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_MULTICAST_HI, ®2, hwsem_put); + stats->rx_ether_multicasts = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_FCS_ERRS_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_FCS_ERRS_LO, ®, hwsem_put); + stats->rx_ether_crc_align_errs = ((uint64_t)reg2 << 32) | reg; + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ALIGN_ERRS_LO, ®2, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ALIGN_ERRS_HI, ®2, hwsem_put); + stats->rx_ether_crc_align_errs += ((uint64_t)reg2 << 32) | reg; + +hwsem_put: + atl_hwsem_put(hw, ATL_MCP_SEM_MSM); + return ret; +} + int atl_update_eth_stats(struct atl_nic *nic) { struct atl_hw *hw = &nic->hw; @@ -1257,34 +1342,13 @@ int atl_update_eth_stats(struct atl_nic *nic) atl_lock_fw(hw); - ret = atl_hwsem_get(hw, ATL_MCP_SEM_MSM); + if (hw->mcp.interface_ver != ATL2_FW_INTERFACE_B0) + ret = __atl_fetch_msm1_stats(hw, &stats); + else + ret = __atl_fetch_msm2_stats(hw, &stats); if (ret) goto unlock_fw; - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PAUSE, ®, hwsem_put); - stats.tx_pause = reg; - - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PAUSE, ®, hwsem_put); - stats.rx_pause = reg; - - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_LO, ®, hwsem_put); - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_OCTETS_HI, ®2, hwsem_put); - stats.rx_ether_octets = ((uint64_t)reg2 << 32) | reg; - - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PKTS_GOOD, ®, hwsem_put); - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ERRS, ®2, hwsem_put); - stats.rx_ether_pkts = reg + reg2;; - - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_BROADCAST, ®, hwsem_put); - stats.rx_ether_broacasts = reg; - - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_MULTICAST, ®, hwsem_put); - stats.rx_ether_multicasts = reg; - - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_FCS_ERRS, ®, hwsem_put); - __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_ALIGN_ERRS, ®2, hwsem_put); - stats.rx_ether_crc_align_errs = reg + reg2; - stats.rx_ether_drops = atl_read(hw, ATL_RX_DMA_STATS_CNT7); /* capture debug counters*/ @@ -1307,8 +1371,6 @@ int atl_update_eth_stats(struct atl_nic *nic) ret = 0; -hwsem_put: - atl_hwsem_put(hw, ATL_MCP_SEM_MSM); unlock_fw: atl_unlock_fw(hw); return ret; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c index 5fe6fa4c1ae5..dbe416f0ac78 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c @@ -443,6 +443,10 @@ int atl_fw_configure(struct atl_hw *hw) !!(nic->priv_flags & ATL_PF_BIT(MEDIA_DETECT))); if (ret && ret != -EOPNOTSUPP) return ret; + ret = hw->mcp.ops->set_downshift(hw, + !!(nic->priv_flags & ATL_PF_BIT(DOWNSHIFT))); + if (ret && ret != -EOPNOTSUPP) + return ret; ret = hw->mcp.ops->set_pad_stripping(hw, !!(nic->priv_flags & ATL_PF_BIT(STRIP_PAD))); if (ret && ret != -EOPNOTSUPP) @@ -598,6 +602,7 @@ static int atl_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_ioremap; } + nic->priv_flags = ATL_PF_BIT(DOWNSHIFT); ret = atl_hwinit(hw, id->driver_data); if (ret) goto err_hwinit; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h index 0edd7dd4d795..341e1b72db15 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h @@ -221,4 +221,22 @@ enum mcp_scratchpad { #define ATL_MSM_CTR_RX_ERRS 0x120 +#define ATL_MSM2_CTR_RX_OCTETS_LO 0x100 +#define ATL_MSM2_CTR_RX_OCTETS_HI 0x104 +#define ATL_MSM2_CTR_RX_ALIGN_ERRS_LO 0x110 +#define ATL_MSM2_CTR_RX_ALIGN_ERRS_HI 0x114 +#define ATL_MSM2_CTR_RX_PAUSE_LO 0x118 +#define ATL_MSM2_CTR_RX_PAUSE_HI 0x11c +#define ATL_MSM2_CTR_RX_FCS_ERRS_LO 0x128 +#define ATL_MSM2_CTR_RX_FCS_ERRS_HI 0x12c +#define ATL_MSM2_CTR_RX_MULTICAST_LO 0x148 +#define ATL_MSM2_CTR_RX_MULTICAST_HI 0x14c +#define ATL_MSM2_CTR_RX_BROADCAST_LO 0x150 +#define ATL_MSM2_CTR_RX_BROADCAST_HI 0x154 +#define ATL_MSM2_CTR_RX_PKTS_LO 0x160 +#define ATL_MSM2_CTR_RX_PKTS_HI 0x164 +#define ATL_MSM2_CTR_TX_PAUSE_LO 0x218 +#define ATL_MSM2_CTR_TX_PAUSE_HI 0x21c + + #endif diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt index 9c2fe9380cb6..307421c4b2b4 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt @@ -1,3 +1,9 @@ +Version 1.1.12 +============== +[ATLDRV-1573] - Crash on enable EEE +[ATLDRV-1576] - FWD: Add support of Antigua B0 statistics +[ATLDRV-1577] - Add Downshift feature + Version 1.1.11 ============== [ATLDRV-1567] - forwarding driver issue with adj_freq From 2260359c5fa5c60389772074b60de52200b62608 Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Thu, 29 Oct 2020 11:41:23 +0300 Subject: [PATCH 2/4] atlantic forwarding driver v1.1.13 [ATLDRV-1581] - AQ091: AQC DMA stats in Ethtool A2: report FW bundle ver instead of mac FW ver. Change-Id: I016ea04bce3ac460048004688d8fb8ef1343b961 Signed-off-by: Dmitry Bogdanov Git-commit: 4349cf87fcd347c0b065544580bf7753f24ca8fa Git-repo: https://github.com/aquantia/linux-4.14-atlantic-forwarding Signed-off-by: Lakshit Tyagi --- .../net/ethernet/aquantia/atlantic-fwd/atl2_fw.c | 4 ++-- .../ethernet/aquantia/atlantic-fwd/atl_common.h | 2 +- .../ethernet/aquantia/atlantic-fwd/atl_ethtool.c | 2 ++ .../net/ethernet/aquantia/atlantic-fwd/atl_hw.c | 15 +++++++++++++++ .../net/ethernet/aquantia/atlantic-fwd/atl_regs.h | 7 +++++++ .../ethernet/aquantia/atlantic-fwd/atl_stats.h | 4 +++- .../aquantia/atlantic-fwd/release_notes.txt | 5 +++++ 7 files changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c index 17a1bcef2f41..0e9b80e6628a 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl2_fw.c @@ -925,8 +925,8 @@ int atl2_get_fw_version(struct atl_hw *hw) struct version_s version; atl2_shared_buffer_read_safe(hw, version, &version); - mcp->fw_rev = version.mac.major << 24 | version.mac.minor << 16 | - version.mac.build; + mcp->fw_rev = version.bundle.major << 24 | version.bundle.minor << 16 | + version.bundle.build; mcp->interface_ver = version.drv_iface_ver; return 0; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h index df90dcaa6f6c..7d2c70781167 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h @@ -20,7 +20,7 @@ #include #include -#define ATL_VERSION "1.1.12" +#define ATL_VERSION "1.1.13" struct atl_nic; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c index a55720b10dfe..a365d2a9cc10 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c @@ -631,6 +631,8 @@ static const struct atl_stat_desc rx_fwd_stat_descs[] = { static const struct atl_stat_desc eth_stat_descs[] = { ATL_ETH_STAT(tx_pause, tx_pause), + ATL_ETH_STAT(tx_ether_pkts, tx_ether_pkts), + ATL_ETH_STAT(tx_ether_octets, tx_ether_octets), ATL_ETH_STAT(rx_pause, rx_pause), ATL_ETH_STAT(rx_ether_drops, rx_ether_drops), ATL_ETH_STAT(rx_ether_octets, rx_ether_octets), diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c index 69aba92c4008..2cf1b09d1a84 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c @@ -1255,6 +1255,13 @@ static int __atl_fetch_msm1_stats(struct atl_hw *hw, __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PAUSE, ®, hwsem_put); stats->tx_pause = reg; + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_PKTS_GOOD, ®, hwsem_put); + stats->tx_ether_pkts = reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_OCTETS_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_TX_OCTETS_HI, ®2, hwsem_put); + stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg; + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM_CTR_RX_PAUSE, ®, hwsem_put); stats->rx_pause = reg; @@ -1295,6 +1302,14 @@ static int __atl_fetch_msm2_stats(struct atl_hw *hw, __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PAUSE_HI, ®2, hwsem_put); stats->tx_pause = ((uint64_t)reg2 << 32) | reg; + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PKTS_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_PKTS_HI, ®2, hwsem_put); + stats->tx_ether_pkts = ((uint64_t)reg2 << 32) | reg; + + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_LO, ®, hwsem_put); + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_HI, ®2, hwsem_put); + stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg; + __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_LO, ®, hwsem_put); __READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_HI, ®2, hwsem_put); stats->rx_pause = ((uint64_t)reg2 << 32) | reg; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h index 341e1b72db15..cbe8fbf5e174 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_regs.h @@ -209,11 +209,14 @@ enum mcp_scratchpad { #define ATL_MSM_GEN_CTRL 0x8 #define ATL_MSM_GEN_STS 0x40 #define ATL_MSM_TX_LPI_DELAY 0x78 +#define ATL_MSM_CTR_TX_PKTS_GOOD 0x80 #define ATL_MSM_CTR_RX_PKTS_GOOD 0x88 #define ATL_MSM_CTR_RX_FCS_ERRS 0x90 #define ATL_MSM_CTR_RX_ALIGN_ERRS 0x98 #define ATL_MSM_CTR_TX_PAUSE 0xa0 #define ATL_MSM_CTR_RX_PAUSE 0xa8 +#define ATL_MSM_CTR_TX_OCTETS_LO 0xd0 +#define ATL_MSM_CTR_TX_OCTETS_HI 0xd4 #define ATL_MSM_CTR_RX_OCTETS_LO 0xd8 #define ATL_MSM_CTR_RX_OCTETS_HI 0xdc #define ATL_MSM_CTR_RX_MULTICAST 0xE8 @@ -235,8 +238,12 @@ enum mcp_scratchpad { #define ATL_MSM2_CTR_RX_BROADCAST_HI 0x154 #define ATL_MSM2_CTR_RX_PKTS_LO 0x160 #define ATL_MSM2_CTR_RX_PKTS_HI 0x164 +#define ATL_MSM2_CTR_TX_OCTETS_LO 0x200 +#define ATL_MSM2_CTR_TX_OCTETS_HI 0x204 #define ATL_MSM2_CTR_TX_PAUSE_LO 0x218 #define ATL_MSM2_CTR_TX_PAUSE_HI 0x21c +#define ATL_MSM2_CTR_TX_PKTS_LO 0x220 +#define ATL_MSM2_CTR_TX_PKTS_HI 0x224 #endif diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_stats.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_stats.h index 0c6b73b7f494..070d078ed61f 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_stats.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_stats.h @@ -52,8 +52,10 @@ struct atl_ring_stats { }; struct atl_ether_stats { - uint64_t rx_pause; uint64_t tx_pause; + uint64_t tx_ether_pkts; + uint64_t tx_ether_octets; + uint64_t rx_pause; uint64_t rx_ether_drops; uint64_t rx_ether_octets; uint64_t rx_ether_pkts; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt index 307421c4b2b4..8addc5beb4f2 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt @@ -1,3 +1,8 @@ +Version 1.1.13 +============== +[ATLDRV-1581] - AQ091: AQC DMA stats in Ethtool +A2: report FW bundle ver instead of mac FW ver + Version 1.1.12 ============== [ATLDRV-1573] - Crash on enable EEE From 10b066c1984505938c3de85df51a95032271359f Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Mon, 23 Nov 2020 14:59:29 +0300 Subject: [PATCH 3/4] atlantic forwarding driver v1.1.14 [ATLDRV-1609] - Facing failure for the DMA Network Loopback Test [ATLDRV-1605] - AQC107 GPIO_0 PPS alignment [ATLDRV-1614] - probe of 0000:02:00.0 failed with error -22 after loading driver with "msi=N max_queues_non_msi=4". Change-Id: Icdad49b4a1f72dee34b7601a72ba4113917931ff Signed-off-by: Dmitry Bogdanov Git-commit: 6288945d8b0ffec0edc1e909b1390cfce3ccb7f0 Git-repo: https://github.com/aquantia/linux-4.14-atlantic-forwarding Signed-off-by: Lakshit Tyagi --- .../aquantia/atlantic-fwd/atl_common.h | 2 +- .../aquantia/atlantic-fwd/atl_fwdnl.c | 2 +- .../ethernet/aquantia/atlantic-fwd/atl_hw.c | 3 ++ .../ethernet/aquantia/atlantic-fwd/atl_ptp.c | 40 ++++++++++++++++++- .../ethernet/aquantia/atlantic-fwd/atl_ring.c | 8 ++-- .../ethernet/aquantia/atlantic-fwd/atl_ring.h | 2 +- .../aquantia/atlantic-fwd/release_notes.txt | 7 ++++ 7 files changed, 56 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h index 7d2c70781167..09055eabb965 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h @@ -20,7 +20,7 @@ #include #include -#define ATL_VERSION "1.1.13" +#define ATL_VERSION "1.1.14" struct atl_nic; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fwdnl.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fwdnl.c index 3e2a98296319..b9e86c4a300d 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fwdnl.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_fwdnl.c @@ -1178,7 +1178,7 @@ static int request_ring(struct net_device *ndev, struct genl_info *info) goto err_relring; } - result = atl_init_rx_ring(ring_desc); + result = atl_init_rx_ring(ring_desc, ATL_QUEUE_REGULAR); } if (result) goto err_relring; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c index 2cf1b09d1a84..b117dd48e6fb 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c @@ -898,6 +898,9 @@ void atl_set_rx_mode(struct net_device *ndev) else if (uc_count + mc_count > nic->rxf_mac.available - 1) all_multi_needed = true; + if (nic->priv_flags & ATL_PF_BIT(LPB_NET_DMA)) + promisc_needed = true; + /* Enable promisc VLAN mode if IFF_PROMISC explicitly * requested or too many VIDs registered */ diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c index 1348fbae126b..2ba0ddc1a0d0 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c @@ -34,6 +34,12 @@ #define PTP_4TC_RING_IDX 16 #define PTP_HWTS_RING_IDX 31 +enum ptp_perout_action { + ptp_perout_disabled = 0, + ptp_perout_enabled, + ptp_perout_pps, +}; + enum ptp_speed_offsets { ptp_offset_idx_10 = 0, ptp_offset_idx_100, @@ -105,6 +111,8 @@ struct ptp_tm_offset { static struct ptp_tm_offset ptp_offset[6]; +static int atl_ptp_pps_reconfigure(struct atl_ptp *ptp); + static int __atl_ptp_skb_put(struct ptp_skb_ring *ring, struct sk_buff *skb) { unsigned int next_head = (ring->head + 1) % ring->size; @@ -309,6 +317,8 @@ static int atl_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) hw_atl_adj_sys_clock(&nic->hw, delta); spin_unlock_irqrestore(&ptp->ptp_lock, flags); + atl_ptp_pps_reconfigure(ptp); + return 0; } @@ -354,9 +364,10 @@ static int atl_ptp_settime(struct ptp_clock_info *ptp_info, spin_lock_irqsave(&ptp->ptp_lock, flags); hw_atl_get_ptp_ts(&nic->hw, &now); hw_atl_adj_sys_clock(&nic->hw, (s64)ns - (s64)now); - spin_unlock_irqrestore(&ptp->ptp_lock, flags); + atl_ptp_pps_reconfigure(ptp); + return 0; } @@ -418,6 +429,8 @@ static int atl_ptp_perout_pin_configure(struct ptp_clock_info *ptp_clock, start = on ? s->sec * NSEC_PER_SEC + s->nsec : 0; atl_ptp_hw_pin_conf(nic, pin_index, start, period); + ptp->ptp_info.pin_config[pin_index].rsv[2] = on ? ptp_perout_enabled : + ptp_perout_disabled; return 0; } @@ -442,10 +455,35 @@ static int atl_ptp_pps_pin_configure(struct ptp_clock_info *ptp_clock, (rest > 990000000LL ? 2 : 1) : 0; atl_ptp_hw_pin_conf(nic, pin_index, start, period); + ptp->ptp_info.pin_config[pin_index].rsv[2] = on ? ptp_perout_pps : + ptp_perout_disabled; return 0; } +static int atl_ptp_pps_reconfigure(struct atl_ptp *ptp) +{ + struct atl_nic *nic = ptp->nic; + u64 start, period; + u32 rest = 0; + int i; + + for (i = 0; i < ptp->ptp_info.n_pins; i++) + if ((ptp->ptp_info.pin_config[i].func == PTP_PF_PEROUT) && + (ptp->ptp_info.pin_config[i].rsv[2] == ptp_perout_pps)) { + + hw_atl_get_ptp_ts(&nic->hw, &start); + div_u64_rem(start, NSEC_PER_SEC, &rest); + period = NSEC_PER_SEC; + start = start - rest + NSEC_PER_SEC * (rest > 990000000LL ? 2 : 1); + + atl_ptp_hw_pin_conf(nic, i, start, period); + } + + return 0; + +} + static void atl_ptp_extts_pin_ctrl(struct atl_ptp *ptp) { struct atl_nic *nic = ptp->nic; diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c index d0b1b3ca3687..b30a04c44ffd 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.c @@ -1825,7 +1825,7 @@ void atl_set_intr_mod(struct atl_nic *nic) atl_set_intr_mod_qvec(qvec); } -int atl_init_rx_ring(struct atl_desc_ring *rx) +int atl_init_rx_ring(struct atl_desc_ring *rx, enum atl_queue_type type) { struct atl_hw *hw = &rx->nic->hw; struct atl_rxbuf *rxbuf; @@ -1835,7 +1835,7 @@ int atl_init_rx_ring(struct atl_desc_ring *rx) if (rx->head > 0x1FFF) return -EIO; - switch (rx->qvec->type) { + switch (type) { case ATL_QUEUE_HWTS: ret = atl_fill_hwts_rx(rx, ring_space(rx), false); break; @@ -1851,7 +1851,7 @@ int atl_init_rx_ring(struct atl_desc_ring *rx) if (ret) return ret; - if (likely(rx->qvec->type != ATL_QUEUE_HWTS)) { + if (likely(type != ATL_QUEUE_HWTS)) { rx->next_to_recycle = rx->tail; /* rxbuf at ->next_to_recycle is always kept empty so that * atl_maybe_recycle_rxbuf() always have a spot to recycle into @@ -1962,7 +1962,7 @@ int atl_start_qvec(struct atl_queue_vec *qvec) int intr = atl_qvec_intr(qvec); int ret; - ret = atl_init_rx_ring(rx); + ret = atl_init_rx_ring(rx, qvec->type); if (ret) return ret; if (likely(qvec->type != ATL_QUEUE_HWTS)) { diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.h index e35bab18a647..8af3f390b8db 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ring.h @@ -186,7 +186,7 @@ do { \ u64_stats_update_end(&_ring->syncp); \ } while (0) -int atl_init_rx_ring(struct atl_desc_ring *rx); +int atl_init_rx_ring(struct atl_desc_ring *rx, enum atl_queue_type type); int atl_init_tx_ring(struct atl_desc_ring *tx); netdev_tx_t atl_map_skb(struct sk_buff *skb, struct atl_desc_ring *ring); diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt index 8addc5beb4f2..153c382a94ed 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt @@ -1,3 +1,10 @@ +Version 1.1.14 +============== +[ATLDRV-1609] - Facing failure for the DMA Network Loopback Test +[ATLDRV-1605] - AQC107 GPIO_0 PPS alignment +[ATLDRV-1614] - probe of 0000:02:00.0 failed with error -22 after loading driver with "msi=N max_queues_non_msi=4" +[ATLDRV-1613] - Atlantic_fwd driver hitting NULL pointer dereference at 0000000000000678 while requesting rx rings + Version 1.1.13 ============== [ATLDRV-1581] - AQ091: AQC DMA stats in Ethtool From 636f35b3614aac6b015f4b11959db51176a56ea1 Mon Sep 17 00:00:00 2001 From: Dmitry Bogdanov Date: Fri, 4 Dec 2020 01:20:48 +0300 Subject: [PATCH 4/4] atlantic forwarding driver v1.1.15 [ATLDRV-1613] - Atlantic_fwd driver hitting NULL pointer dereference at 0000000000000678 while requesting rx rings. Change-Id: I89984d94d6093655ea5596cb1f297fc548cc42b4 Signed-off-by: Dmitry Bogdanov Git-commit: 3dc6f4c6d29722da5e0f1a9894bb9b608c0d38a3 Git-repo: https://github.com/aquantia/linux-4.14-atlantic-forwarding [ltyagi@codeaurora.org: Fix compilation error in atl_ptp_irq] Signed-off-by: Lakshit Tyagi --- .../aquantia/atlantic-fwd/atl_common.h | 3 +- .../ethernet/aquantia/atlantic-fwd/atl_hw.c | 4 +- .../ethernet/aquantia/atlantic-fwd/atl_ptp.c | 39 +++++++++++-------- .../aquantia/atlantic-fwd/release_notes.txt | 5 ++- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h index 09055eabb965..717a36f27bc6 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h @@ -20,7 +20,7 @@ #include #include -#define ATL_VERSION "1.1.14" +#define ATL_VERSION "1.1.15" struct atl_nic; @@ -400,6 +400,7 @@ void atl_clear_tdm_cache(struct atl_nic *nic); int atl_alloc_rings(struct atl_nic *nic); void atl_free_rings(struct atl_nic *nic); irqreturn_t atl_ring_irq(int irq, void *priv); +irqreturn_t atl_ptp_irq(int irq, void *private); void atl_ring_work(struct work_struct *work); void atl_start_hw_global(struct atl_nic *nic); int atl_intr_init(struct atl_nic *nic); diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c index b117dd48e6fb..c3d47216e8a2 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c @@ -575,8 +575,10 @@ static irqreturn_t atl_legacy_irq(int irq, void *priv) } } - if (unlikely(stat & hw->non_ring_intr_mask)) + if (unlikely(stat & BIT(ATL_IRQ_LINK))) atl_link_irq(irq, nic); + if (unlikely(stat & BIT(ATL_IRQ_PTP))) + atl_ptp_irq(irq, nic->ptp); return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c index 2ba0ddc1a0d0..622ba980a20f 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_ptp.c @@ -613,21 +613,6 @@ static int atl_ptp_poll(struct napi_struct *napi, int budget) return work_done; } -static irqreturn_t atl_ptp_irq(int irq, void *private) -{ - struct atl_ptp *ptp = private; - int err = 0; - - if (!ptp) { - err = -EINVAL; - goto err_exit; - } - napi_schedule_irqoff(ptp->napi); - -err_exit: - return err >= 0 ? IRQ_HANDLED : IRQ_NONE; -} - static struct ptp_clock_info atl_ptp_clock = { .owner = THIS_MODULE, .name = "atlantic ptp", @@ -846,6 +831,25 @@ static void atl_ptp_poll_sync_work_cb(struct work_struct *w) #endif /* IS_REACHABLE(CONFIG_PTP_1588_CLOCK) */ +irqreturn_t atl_ptp_irq(int irq, void *private) +{ +#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + struct atl_ptp *ptp = private; + int err = 0; + + if (!ptp) { + err = -EINVAL; + goto err_exit; + } + napi_schedule_irqoff(ptp->napi); + +err_exit: + return err >= 0 ? IRQ_HANDLED : IRQ_NONE; +#else + return IRQ_NONE; +#endif +} + void atl_ptp_tm_offset_set(struct atl_nic *nic, unsigned int mbps) { #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) @@ -1068,7 +1072,7 @@ int atl_ptp_irq_alloc(struct atl_nic *nic) atl_ptp_irq, 0, nic->ndev->name, ptp); } - return -EINVAL; + return 0; #else return 0; #endif @@ -1084,7 +1088,8 @@ void atl_ptp_irq_free(struct atl_nic *nic) return; atl_intr_disable(hw, BIT(ptp->idx_vector)); - free_irq(pci_irq_vector(hw->pdev, ptp->idx_vector), ptp); + if (nic->flags & ATL_FL_MULTIPLE_VECTORS) + free_irq(pci_irq_vector(hw->pdev, ptp->idx_vector), ptp); #endif } diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt index 153c382a94ed..8e5b07ce42b6 100644 --- a/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt +++ b/drivers/net/ethernet/aquantia/atlantic-fwd/release_notes.txt @@ -1,9 +1,12 @@ +Version 1.1.15 +============== +[ATLDRV-1613] - Atlantic_fwd driver hitting NULL pointer dereference at 0000000000000678 while requesting rx rings + Version 1.1.14 ============== [ATLDRV-1609] - Facing failure for the DMA Network Loopback Test [ATLDRV-1605] - AQC107 GPIO_0 PPS alignment [ATLDRV-1614] - probe of 0000:02:00.0 failed with error -22 after loading driver with "msi=N max_queues_non_msi=4" -[ATLDRV-1613] - Atlantic_fwd driver hitting NULL pointer dereference at 0000000000000678 while requesting rx rings Version 1.1.13 ==============