From 2102db8793c8d4ae4fcf5c608921e82c1d09dc46 Mon Sep 17 00:00:00 2001 From: Jiawen Wu Date: Mon, 19 Oct 2020 16:53:54 +0800 Subject: [PATCH] net/txgbe: add SWFW semaphore and lock Add semaphore between software and firmware. Signed-off-by: Jiawen Wu Reviewed-by: Ferruh Yigit --- drivers/net/txgbe/base/txgbe_dummy.h | 2 +- drivers/net/txgbe/base/txgbe_eeprom.h | 8 ++ drivers/net/txgbe/base/txgbe_hw.c | 129 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_hw.h | 5 + drivers/net/txgbe/base/txgbe_type.h | 2 +- drivers/net/txgbe/txgbe_ethdev.c | 29 ++++++ 6 files changed, 173 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_dummy.h b/drivers/net/txgbe/base/txgbe_dummy.h index 495daa18a4..0a3a76d0c0 100644 --- a/drivers/net/txgbe/base/txgbe_dummy.h +++ b/drivers/net/txgbe/base/txgbe_dummy.h @@ -326,7 +326,7 @@ static inline void txgbe_mac_fc_autoneg_dummy(struct txgbe_hw *TUP0) { } static inline s32 txgbe_mac_set_fw_drv_ver_dummy(struct txgbe_hw *TUP0, u8 TUP1, - u8 TUP2, u8 TUP3, u8 TUP4, u16 TUP5, char *TUP6) + u8 TUP2, u8 TUP3, u8 TUP4, u16 TUP5, const char *TUP6) { return TXGBE_ERR_OPS_DUMMY; } diff --git a/drivers/net/txgbe/base/txgbe_eeprom.h b/drivers/net/txgbe/base/txgbe_eeprom.h index 2ad6c7e19a..d0e142dba5 100644 --- a/drivers/net/txgbe/base/txgbe_eeprom.h +++ b/drivers/net/txgbe/base/txgbe_eeprom.h @@ -30,6 +30,14 @@ #define TXGBE_FW_LESM_PARAMETERS_PTR 0x2 #define TXGBE_FW_LESM_STATE_1 0x1 #define TXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */ +#define TXGBE_ALT_SAN_MAC_ADDR_BLK_PTR 0x27 /* Alt. SAN MAC block */ +#define TXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET 0x0 /* Alt SAN MAC capability */ +#define TXGBE_ALT_SAN_MAC_ADDR_PORT0_OFFSET 0x1 /* Alt SAN MAC 0 offset */ +#define TXGBE_ALT_SAN_MAC_ADDR_PORT1_OFFSET 0x4 /* Alt SAN MAC 1 offset */ +#define TXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET 0x7 /* Alt WWNN prefix offset */ +#define TXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET 0x8 /* Alt WWPN prefix offset */ +#define TXGBE_ALT_SAN_MAC_ADDR_CAPS_SANMAC 0x0 /* Alt SAN MAC exists */ +#define TXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt WWN base exists */ s32 txgbe_init_eeprom_params(struct txgbe_hw *hw); s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw); diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index f3524ec2be..1b1d1525f7 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -670,6 +670,77 @@ s32 txgbe_update_mc_addr_list(struct txgbe_hw *hw, u8 *mc_addr_list, return 0; } +/** + * txgbe_acquire_swfw_sync - Acquire SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to acquire + * + * Acquires the SWFW semaphore through the MNGSEM register for the specified + * function (CSR, PHY0, PHY1, EEPROM, Flash) + **/ +s32 txgbe_acquire_swfw_sync(struct txgbe_hw *hw, u32 mask) +{ + u32 mngsem = 0; + u32 swmask = TXGBE_MNGSEM_SW(mask); + u32 fwmask = TXGBE_MNGSEM_FW(mask); + u32 timeout = 200; + u32 i; + + DEBUGFUNC("txgbe_acquire_swfw_sync"); + + for (i = 0; i < timeout; i++) { + /* + * SW NVM semaphore bit is used for access to all + * SW_FW_SYNC bits (not just NVM) + */ + if (txgbe_get_eeprom_semaphore(hw)) + return TXGBE_ERR_SWFW_SYNC; + + mngsem = rd32(hw, TXGBE_MNGSEM); + if (mngsem & (fwmask | swmask)) { + /* Resource is currently in use by FW or SW */ + txgbe_release_eeprom_semaphore(hw); + msec_delay(5); + } else { + mngsem |= swmask; + wr32(hw, TXGBE_MNGSEM, mngsem); + txgbe_release_eeprom_semaphore(hw); + return 0; + } + } + + /* If time expired clear the bits holding the lock and retry */ + if (mngsem & (fwmask | swmask)) + txgbe_release_swfw_sync(hw, mngsem & (fwmask | swmask)); + + msec_delay(5); + return TXGBE_ERR_SWFW_SYNC; +} + +/** + * txgbe_release_swfw_sync - Release SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to release + * + * Releases the SWFW semaphore through the MNGSEM register for the specified + * function (CSR, PHY0, PHY1, EEPROM, Flash) + **/ +void txgbe_release_swfw_sync(struct txgbe_hw *hw, u32 mask) +{ + u32 mngsem; + u32 swmask = mask; + + DEBUGFUNC("txgbe_release_swfw_sync"); + + txgbe_get_eeprom_semaphore(hw); + + mngsem = rd32(hw, TXGBE_MNGSEM); + mngsem &= ~swmask; + wr32(hw, TXGBE_MNGSEM, mngsem); + + txgbe_release_eeprom_semaphore(hw); +} + /** * txgbe_disable_sec_rx_path - Stops the receive data path * @hw: pointer to hardware structure @@ -1047,6 +1118,60 @@ s32 txgbe_check_mac_link(struct txgbe_hw *hw, u32 *speed, return 0; } +/** + * txgbe_get_wwn_prefix - Get alternative WWNN/WWPN prefix from + * the EEPROM + * @hw: pointer to hardware structure + * @wwnn_prefix: the alternative WWNN prefix + * @wwpn_prefix: the alternative WWPN prefix + * + * This function will read the EEPROM from the alternative SAN MAC address + * block to check the support for the alternative WWNN/WWPN prefix support. + **/ +s32 txgbe_get_wwn_prefix(struct txgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix) +{ + u16 offset, caps; + u16 alt_san_mac_blk_offset; + + DEBUGFUNC("txgbe_get_wwn_prefix"); + + /* clear output first */ + *wwnn_prefix = 0xFFFF; + *wwpn_prefix = 0xFFFF; + + /* check if alternative SAN MAC is supported */ + offset = TXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; + if (hw->rom.readw_sw(hw, offset, &alt_san_mac_blk_offset)) + goto wwn_prefix_err; + + if (alt_san_mac_blk_offset == 0 || alt_san_mac_blk_offset == 0xFFFF) + goto wwn_prefix_out; + + /* check capability in alternative san mac address block */ + offset = alt_san_mac_blk_offset + TXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; + if (hw->rom.read16(hw, offset, &caps)) + goto wwn_prefix_err; + if (!(caps & TXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) + goto wwn_prefix_out; + + /* get the corresponding prefix for WWNN/WWPN */ + offset = alt_san_mac_blk_offset + TXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; + if (hw->rom.read16(hw, offset, wwnn_prefix)) + DEBUGOUT("eeprom read at offset %d failed", offset); + + offset = alt_san_mac_blk_offset + TXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; + if (hw->rom.read16(hw, offset, wwpn_prefix)) + goto wwn_prefix_err; + +wwn_prefix_out: + return 0; + +wwn_prefix_err: + DEBUGOUT("eeprom read at offset %d failed", offset); + return 0; +} + /** * txgbe_get_device_caps - Get additional device capabilities * @hw: pointer to hardware structure @@ -1605,6 +1730,8 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) mac->enable_rx_dma = txgbe_enable_rx_dma_raptor; mac->get_mac_addr = txgbe_get_mac_addr; mac->stop_hw = txgbe_stop_hw; + mac->acquire_swfw_sync = txgbe_acquire_swfw_sync; + mac->release_swfw_sync = txgbe_release_swfw_sync; mac->reset_hw = txgbe_reset_hw; mac->disable_sec_rx_path = txgbe_disable_sec_rx_path; @@ -1614,6 +1741,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) mac->get_san_mac_addr = txgbe_get_san_mac_addr; mac->set_san_mac_addr = txgbe_set_san_mac_addr; mac->get_device_caps = txgbe_get_device_caps; + mac->get_wwn_prefix = txgbe_get_wwn_prefix; mac->autoc_read = txgbe_autoc_read; mac->autoc_write = txgbe_autoc_write; @@ -1630,6 +1758,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) mac->check_link = txgbe_check_mac_link; /* Manageability interface */ + mac->set_fw_drv_ver = txgbe_hic_set_drv_ver; mac->get_thermal_sensor_data = txgbe_get_thermal_sensor_data; mac->init_thermal_sensor_thresh = txgbe_init_thermal_sensor_thresh; diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index ac4f7fbe8d..cba5876e82 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -29,6 +29,8 @@ s32 txgbe_disable_sec_tx_path(struct txgbe_hw *hw); s32 txgbe_enable_sec_tx_path(struct txgbe_hw *hw); s32 txgbe_validate_mac_addr(u8 *mac_addr); +s32 txgbe_acquire_swfw_sync(struct txgbe_hw *hw, u32 mask); +void txgbe_release_swfw_sync(struct txgbe_hw *hw, u32 mask); s32 txgbe_get_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr); s32 txgbe_set_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr); @@ -39,6 +41,9 @@ s32 txgbe_check_mac_link(struct txgbe_hw *hw, u32 *speed, bool *link_up, bool link_up_wait_to_complete); +s32 txgbe_get_wwn_prefix(struct txgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix); + s32 txgbe_get_device_caps(struct txgbe_hw *hw, u16 *device_caps); void txgbe_clear_tx_pending(struct txgbe_hw *hw); diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index dc038a5ba1..539d1fb4d4 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -483,7 +483,7 @@ struct txgbe_mac_info { /* Manageability interface */ s32 (*set_fw_drv_ver)(struct txgbe_hw *hw, u8 maj, u8 min, u8 build, - u8 ver, u16 len, char *driver_ver); + u8 ver, u16 len, const char *driver_ver); s32 (*get_thermal_sensor_data)(struct txgbe_hw *hw); s32 (*init_thermal_sensor_thresh)(struct txgbe_hw *hw); void (*get_rtrup2tc)(struct txgbe_hw *hw, u8 *map); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 118ba31f0d..999bf27e2e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -336,6 +336,29 @@ txgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev, return 0; } +/* + * Ensure that all locks are released before first NVM or PHY access + */ +static void +txgbe_swfw_lock_reset(struct txgbe_hw *hw) +{ + uint16_t mask; + + /* + * These ones are more tricky since they are common to all ports; but + * swfw_sync retries last long enough (1s) to be almost sure that if + * lock can not be taken it is due to an improper lock of the + * semaphore. + */ + mask = TXGBE_MNGSEM_SWPHY | + TXGBE_MNGSEM_SWMBX | + TXGBE_MNGSEM_SWFLASH; + if (hw->mac.acquire_swfw_sync(hw, mask) < 0) + PMD_DRV_LOG(DEBUG, "SWFW common locks released"); + + hw->mac.release_swfw_sync(hw, mask); +} + static int eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { @@ -404,6 +427,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Unlock any pending hardware semaphore */ + txgbe_swfw_lock_reset(hw); + err = hw->rom.init_params(hw); if (err != 0) { PMD_INIT_LOG(ERR, "The EEPROM init failed: %d", err); @@ -1453,6 +1479,9 @@ txgbe_dev_close(struct rte_eth_dev *dev) /* reprogram the RAR[0] in case user changed it. */ txgbe_set_rar(hw, 0, hw->mac.addr, 0, true); + /* Unlock any pending hardware semaphore */ + txgbe_swfw_lock_reset(hw); + /* disable uio intr before callback unregister */ rte_intr_disable(intr_handle); -- 2.20.1