diff options
Diffstat (limited to 'drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c')
| -rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c | 99 |
1 files changed, 89 insertions, 10 deletions
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c index 5f13465995f6..18b08277d2e1 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c @@ -1,10 +1,8 @@ -/* - * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +// SPDX-License-Identifier: GPL-2.0-only +/* Atlantic Network Driver * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. + * Copyright (C) 2014-2019 aQuantia Corporation + * Copyright (C) 2019-2020 Marvell International Ltd. */ /* File aq_hw_utils.c: Definitions of helper functions used across @@ -12,7 +10,12 @@ */ #include "aq_hw_utils.h" + +#include <linux/io-64-nonatomic-lo-hi.h> + #include "aq_hw.h" +#include "aq_nic.h" +#include "hw_atl/hw_atl_llh.h" void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, u32 shift, u32 val) @@ -39,8 +42,9 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg) { u32 value = readl(hw->mmio + reg); - if ((~0U) == value && (~0U) == readl(hw->mmio + hw->not_ff_addr)) - aq_utils_obj_set(&hw->header.flags, AQ_HW_FLAG_ERR_UNPLUG); + if (value == U32_MAX && + readl(hw->mmio + hw->aq_nic_cfg->aq_hw_caps->hw_alive_check_addr) == U32_MAX) + aq_utils_obj_set(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG); return value; } @@ -50,15 +54,64 @@ void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value) writel(value, hw->mmio + reg); } +/* Most of 64-bit registers are in LSW, MSW form. + Counters are normally implemented by HW as latched pairs: + reading LSW first locks MSW, to overcome LSW overflow + */ +u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg) +{ + u64 value = U64_MAX; + + if (hw->aq_nic_cfg->aq_hw_caps->op64bit) + value = readq(hw->mmio + reg); + else + value = lo_hi_readq(hw->mmio + reg); + + if (value == U64_MAX && + readl(hw->mmio + hw->aq_nic_cfg->aq_hw_caps->hw_alive_check_addr) == U32_MAX) + aq_utils_obj_set(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG); + + return value; +} + +void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) +{ + if (hw->aq_nic_cfg->aq_hw_caps->op64bit) + writeq(value, hw->mmio + reg); + else + lo_hi_writeq(value, hw->mmio + reg); +} + +int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) +{ + int err; + u32 val; + + /* Invalidate Descriptor Cache to prevent writing to the cached + * descriptors and to the data pointer of those descriptors + */ + hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); + + err = aq_hw_err_from_flags(hw); + if (err) + goto err_exit; + + readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, + hw, val, val == 1, 1000U, 10000U); + +err_exit: + return err; +} + int aq_hw_err_from_flags(struct aq_hw_s *hw) { int err = 0; - if (aq_utils_obj_test(&hw->header.flags, AQ_HW_FLAG_ERR_UNPLUG)) { + if (aq_utils_obj_test(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG)) { err = -ENXIO; goto err_exit; } - if (aq_utils_obj_test(&hw->header.flags, AQ_HW_FLAG_ERR_HW)) { + if (aq_utils_obj_test(&hw->flags, AQ_HW_FLAG_ERR_HW)) { err = -EIO; goto err_exit; } @@ -66,3 +119,29 @@ int aq_hw_err_from_flags(struct aq_hw_s *hw) err_exit: return err; } + +int aq_hw_num_tcs(struct aq_hw_s *hw) +{ + switch (hw->aq_nic_cfg->tc_mode) { + case AQ_TC_MODE_8TCS: + return 8; + case AQ_TC_MODE_4TCS: + return 4; + default: + break; + } + + return 1; +} + +int aq_hw_q_per_tc(struct aq_hw_s *hw) +{ + switch (hw->aq_nic_cfg->tc_mode) { + case AQ_TC_MODE_8TCS: + return 4; + case AQ_TC_MODE_4TCS: + return 8; + default: + return 4; + } +} |
