From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1BB3DA04AC; Tue, 1 Sep 2020 13:52:45 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D9CC81C119; Tue, 1 Sep 2020 13:51:21 +0200 (CEST) Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) by dpdk.org (Postfix) with ESMTP id 3E0651C0B7 for ; Tue, 1 Sep 2020 13:51:16 +0200 (CEST) X-QQ-mid: bizesmtp5t1598961071t18c98nlp Received: from localhost.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Tue, 01 Sep 2020 19:51:10 +0800 (CST) X-QQ-SSF: 01400000000000B0C000000A0000000 X-QQ-FEAT: ChTsRoALjQBQN6fuOTHFt79wJJhAGJYENcVxRRb09SxBX57rfawfXSM9gQqxV XBMdMHlZv98W8n6g0wF0PwwJJEGDb+l6WtUmUAp5nwNbtgxnGpYTL/emuXeu2MuWFlCoBe7 fc6/F9a67xsQl7hXf2o3nzZnsHSgBE20xYmTGa1UW0XyWme1baVtaHo3rIt++Isx7ptnCyM GnL/LHVFazzG0WLqxhPvT9ltq4J1ymdn/OP4TwMlHrZVsgdBEPx/nwenea4mhqryIJgGqBu JqBQlByTLWH0eMaPDvHL0OD3/pygvsxozPoNY1ETwdkz9LRmMbCop7hr7N/6KeQsBvTaKt3 zUVzgA6t4P31tWv5ZDY/jSn5mtJJw== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Tue, 1 Sep 2020 19:50:39 +0800 Message-Id: <20200901115113.1529675-8-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.18.4 In-Reply-To: <20200901115113.1529675-1-jiawenwu@trustnetic.com> References: <20200901115113.1529675-1-jiawenwu@trustnetic.com> X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v1 08/42] net/txgbe: add HW reset operation X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add hardware reset operation. Signed-off-by: Jiawen Wu --- drivers/net/txgbe/base/txgbe_hw.c | 298 +++++++++++++++++++++++++++- drivers/net/txgbe/base/txgbe_hw.h | 5 + drivers/net/txgbe/base/txgbe_type.h | 12 ++ 3 files changed, 304 insertions(+), 11 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index c644de864..9a77adc72 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -5,6 +5,7 @@ #include "txgbe_type.h" #include "txgbe_vf.h" #include "txgbe_eeprom.h" +#include "txgbe_mng.h" #include "txgbe_hw.h" /** @@ -69,18 +70,131 @@ s32 txgbe_init_hw(struct txgbe_hw *hw) return status; } +/** + * txgbe_validate_mac_addr - Validate MAC address + * @mac_addr: pointer to MAC address. + * + * Tests a MAC address to ensure it is a valid Individual Address. + **/ +s32 txgbe_validate_mac_addr(u8 *mac_addr) +{ + s32 status = 0; + + DEBUGFUNC("txgbe_validate_mac_addr"); + + /* Make sure it is not a multicast address */ + if (TXGBE_IS_MULTICAST(mac_addr)) { + status = TXGBE_ERR_INVALID_MAC_ADDR; + /* Not a broadcast address */ + } else if (TXGBE_IS_BROADCAST(mac_addr)) { + status = TXGBE_ERR_INVALID_MAC_ADDR; + /* Reject the zero address */ + } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && + mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { + status = TXGBE_ERR_INVALID_MAC_ADDR; + } + return status; +} + s32 txgbe_set_rar(struct txgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr) { - RTE_SET_USED(hw); - RTE_SET_USED(index); - RTE_SET_USED(addr); - RTE_SET_USED(vmdq); - RTE_SET_USED(enable_addr); + u32 rar_low, rar_high; + u32 rar_entries = hw->mac.num_rar_entries; - return 0; + DEBUGFUNC("txgbe_set_rar"); + + /* Make sure we are using a valid rar index range */ + if (index >= rar_entries) { + DEBUGOUT("RAR index %d is out of range.\n", index); + return TXGBE_ERR_INVALID_ARGUMENT; + } + + /* setup VMDq pool selection before this RAR gets enabled */ + hw->mac.set_vmdq(hw, index, vmdq); + + /* + * HW expects these in little endian so we reverse the byte + * order from network order (big endian) to little endian + */ + rar_low = TXGBE_ETHADDRL_AD0(addr[5]) | + TXGBE_ETHADDRL_AD1(addr[4]) | + TXGBE_ETHADDRL_AD2(addr[3]) | + TXGBE_ETHADDRL_AD3(addr[2]); + /* + * Some parts put the VMDq setting in the extra RAH bits, + * so save everything except the lower 16 bits that hold part + * of the address and the address valid bit. + */ + rar_high = rd32(hw, TXGBE_ETHADDRH); + rar_high &= ~TXGBE_ETHADDRH_AD_MASK; + rar_high |= (TXGBE_ETHADDRH_AD4(addr[1]) | + TXGBE_ETHADDRH_AD5(addr[0])); + + rar_high &= ~TXGBE_ETHADDRH_VLD; + if (enable_addr != 0) + rar_high |= TXGBE_ETHADDRH_VLD; + + wr32(hw, TXGBE_ETHADDRIDX, index); + wr32(hw, TXGBE_ETHADDRL, rar_low); + wr32(hw, TXGBE_ETHADDRH, rar_high); +} + +/** + * txgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo + * @hw: pointer to the hardware structure + * + * The MACs can experience issues if TX work is still pending + * when a reset occurs. This function prevents this by flushing the PCIe + * buffers on the system. + **/ +void txgbe_clear_tx_pending(struct txgbe_hw *hw) +{ + u32 hlreg0, i, poll; + + /* + * If double reset is not requested then all transactions should + * already be clear and as such there is no work to do + */ + if (!(hw->mac.flags & TXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) + return; + + hlreg0 = rd32(hw, TXGBE_PSRCTL); + wr32(hw, TXGBE_PSRCTL, hlreg0 | TXGBE_PSRCTL_LBENA); + + /* Wait for a last completion before clearing buffers */ + txgbe_flush(hw); + msec_delay(3); + + /* + * Before proceeding, make sure that the PCIe block does not have + * transactions pending. + */ + poll = (800 * 11) / 10; + for (i = 0; i < poll; i++) { + usec_delay(100); + } + + /* Flush all writes and allow 20usec for all transactions to clear */ + txgbe_flush(hw); + usec_delay(20); + + /* restore previous register values */ + wr32(hw, TXGBE_PSRCTL, hlreg0); } +/** + * txgbe_init_shared_code - Initialize the shared code + * @hw: pointer to hardware structure + * + * This will assign function pointers and assign the MAC type and PHY code. + * Does not touch the hardware. This function must be called prior to any + * other function in the shared code. The txgbe_hw structure should be + * memset to 0 prior to calling this function. The following fields in + * hw structure should be filled in prior to calling this function: + * hw_addr, back, device_id, vendor_id, subsystem_device_id, + * subsystem_vendor_id, and revision_id + **/ s32 txgbe_init_shared_code(struct txgbe_hw *hw) { s32 status; @@ -109,7 +223,6 @@ s32 txgbe_init_shared_code(struct txgbe_hw *hw) hw->bus.set_lan_id(hw); return status; - } /** @@ -172,6 +285,11 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) struct txgbe_mac_info *mac = &hw->mac; struct txgbe_rom_info *rom = &hw->rom; + /* MAC */ + mac->init_hw = txgbe_init_hw; + mac->start_hw = txgbe_start_hw_raptor; + mac->reset_hw = txgbe_reset_hw; + /* EEPROM */ rom->init_params = txgbe_init_eeprom_params; rom->read16 = txgbe_ee_read16; @@ -186,13 +304,171 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) rom->update_checksum = txgbe_update_eeprom_checksum; rom->calc_checksum = txgbe_calc_eeprom_checksum; - /* MAC */ - mac->init_hw = txgbe_init_hw; - mac->start_hw = txgbe_start_hw_raptor; - return 0; } +static int +txgbe_check_flash_load(struct txgbe_hw *hw, u32 check_bit) +{ + u32 reg = 0; + u32 i; + int err = 0; + /* if there's flash existing */ + if (!(rd32(hw, TXGBE_SPISTAT) & TXGBE_SPISTAT_BPFLASH)) { + /* wait hw load flash done */ + for (i = 0; i < 10; i++) { + reg = rd32(hw, TXGBE_ILDRSTAT); + if (!(reg & check_bit)) { + /* done */ + break; + } + msleep(100); + } + if (i == 10) { + err = TXGBE_ERR_FLASH_LOADING_FAILED; + } + } + return err; +} + +static void +txgbe_reset_misc(struct txgbe_hw *hw) +{ + RTE_SET_USED(hw); +} + +/** + * txgbe_reset_hw - Perform hardware reset + * @hw: pointer to hardware structure + * + * Resets the hardware by resetting the transmit and receive units, masks + * and clears all interrupts, perform a PHY reset, and perform a link (MAC) + * reset. + **/ +s32 txgbe_reset_hw(struct txgbe_hw *hw) +{ + s32 status; + u32 autoc; + + DEBUGFUNC("txgbe_reset_hw"); + + /* Call adapter stop to disable tx/rx and clear interrupts */ + status = hw->mac.stop_hw(hw); + if (status != 0) + return status; + + /* flush pending Tx transactions */ + txgbe_clear_tx_pending(hw); + + /* Identify PHY and related function pointers */ + status = hw->phy.init(hw); + if (status == TXGBE_ERR_SFP_NOT_SUPPORTED) + return status; + + /* Setup SFP module if there is one present. */ + if (hw->phy.sfp_setup_needed) { + status = hw->mac.setup_sfp(hw); + hw->phy.sfp_setup_needed = false; + } + if (status == TXGBE_ERR_SFP_NOT_SUPPORTED) + return status; + + /* Reset PHY */ + if (hw->phy.reset_disable == false) + hw->phy.reset(hw); + + /* remember AUTOC from before we reset */ + autoc = hw->mac.autoc_read(hw); + +mac_reset_top: + /* + * Issue global reset to the MAC. Needs to be SW reset if link is up. + * If link reset is used when link is up, it might reset the PHY when + * mng is using it. If link is down or the flag to force full link + * reset is set, then perform link reset. + */ + if (txgbe_mng_present(hw)) { + txgbe_hic_reset(hw); + } else { + wr32(hw, TXGBE_RST, TXGBE_RST_LAN(hw->bus.lan_id)); + txgbe_flush(hw); + } + usec_delay(10); + + txgbe_reset_misc(hw); + + if (hw->bus.lan_id == 0) { + status = txgbe_check_flash_load(hw, + TXGBE_ILDRSTAT_SWRST_LAN0); + } else { + status = txgbe_check_flash_load(hw, + TXGBE_ILDRSTAT_SWRST_LAN1); + } + if (status != 0) + return status; + + msec_delay(50); + + /* + * Double resets are required for recovery from certain error + * conditions. Between resets, it is necessary to stall to + * allow time for any pending HW events to complete. + */ + if (hw->mac.flags & TXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { + hw->mac.flags &= ~TXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + goto mac_reset_top; + } + + /* + * Store the original AUTOC/AUTOC2 values if they have not been + * stored off yet. Otherwise restore the stored original + * values since the reset operation sets back to defaults. + */ + if (hw->mac.orig_link_settings_stored == false) { + hw->mac.orig_autoc = hw->mac.autoc_read(hw); + hw->mac.autoc_write(hw, hw->mac.orig_autoc); + hw->mac.orig_link_settings_stored = true; + } else { + hw->mac.orig_autoc = autoc; + } + + /* Store the permanent mac address */ + hw->mac.get_mac_addr(hw, hw->mac.perm_addr); + + /* + * Store MAC address from RAR0, clear receive address registers, and + * clear the multicast table. Also reset num_rar_entries to 128, + * since we modify this value when programming the SAN MAC address. + */ + hw->mac.num_rar_entries = 128; + hw->mac.init_rx_addrs(hw); + + /* Store the permanent SAN mac address */ + hw->mac.get_san_mac_addr(hw, hw->mac.san_addr); + + /* Add the SAN MAC address to the RAR only if it's a valid address */ + if (txgbe_validate_mac_addr(hw->mac.san_addr) == 0) { + /* Save the SAN MAC RAR index */ + hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1; + + hw->mac.set_rar(hw, hw->mac.san_mac_rar_index, + hw->mac.san_addr, 0, true); + + /* clear VMDq pool/queue selection for this RAR */ + hw->mac.clear_vmdq(hw, hw->mac.san_mac_rar_index, + BIT_MASK32); + + /* Reserve the last RAR for the SAN MAC address */ + hw->mac.num_rar_entries--; + } + + /* Store the alternative WWNN/WWPN prefix */ + hw->mac.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, + &hw->mac.wwpn_prefix); + + return status; +} + /** * txgbe_start_hw_raptor - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index 55b1b60de..a2816c40a 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -15,7 +15,12 @@ s32 txgbe_start_hw_raptor(struct txgbe_hw *hw); s32 txgbe_set_rar(struct txgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); + +s32 txgbe_validate_mac_addr(u8 *mac_addr); +void txgbe_clear_tx_pending(struct txgbe_hw *hw); s32 txgbe_init_shared_code(struct txgbe_hw *hw); s32 txgbe_set_mac_type(struct txgbe_hw *hw); s32 txgbe_init_ops_pf(struct txgbe_hw *hw); +s32 txgbe_reset_hw(struct txgbe_hw *hw); +s32 txgbe_start_hw_raptor(struct txgbe_hw *hw); #endif /* _TXGBE_HW_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 92068b6f7..f8ac41fe9 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -207,6 +207,7 @@ struct txgbe_flash_info { u16 address_bits; }; +#define TXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01 struct txgbe_mac_info { s32 (*init_hw)(struct txgbe_hw *); s32 (*reset_hw)(struct txgbe_hw *); @@ -316,9 +317,18 @@ struct txgbe_mac_info { u8 addr[ETH_ADDR_LEN]; u8 perm_addr[ETH_ADDR_LEN]; u8 san_addr[ETH_ADDR_LEN]; + /* prefix for World Wide Node Name (WWNN) */ + u16 wwnn_prefix; + /* prefix for World Wide Port Name (WWPN) */ + u16 wwpn_prefix; u32 num_rar_entries; + + u8 san_mac_rar_index; + u64 orig_autoc; /* cached value of AUTOC */ + bool orig_link_settings_stored; bool autotry_restart; + u8 flags; u32 max_link_up_time; }; @@ -354,6 +364,8 @@ struct txgbe_phy_info { enum txgbe_phy_type type; enum txgbe_sfp_type sfp_type; + bool sfp_setup_needed; + bool reset_disable; }; struct txgbe_mbx_info { -- 2.18.4