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 C663CA04AC; Tue, 1 Sep 2020 13:57:52 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 12B4F1C2A3; Tue, 1 Sep 2020 13:51:54 +0200 (CEST) Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) by dpdk.org (Postfix) with ESMTP id 0EBFE1C1D8 for ; Tue, 1 Sep 2020 13:51:44 +0200 (CEST) X-QQ-mid: bizesmtp5t1598961101tiqwv6r2x Received: from localhost.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Tue, 01 Sep 2020 19:51:40 +0800 (CST) X-QQ-SSF: 01400000000000B0C000000A0000000 X-QQ-FEAT: O0I776c7Ory/+i+aRcWwtOIzqoc7wfkxuyuxQMSK5v/K+hNdzdY0AgAbUhKBH ZCasuYFzd5ZWIkHVBXY5VONuIUAmFcmw7Hyz6owIYHxozWcxgBDhuORFIMtN8kvMFBs99if HINW3EHj3F3c4+DObp50MXCQW7KI9WpyCxfmxg+kt2PBVGP2Uvyl3sZp7bR4IbXl2DqE9I1 1ojfId86gujlyMawiN15OshNCLMFigwAar5uDSY3nuA7svyeTzIUaogw/yEG+BeMR04xmts 9Eu/5REVma+3NWmFGJY9ZRgZ6x0jc6sXXmc/DcvSWIVcOXLnLlzU3R6MYpP7uPHn4vDYi+7 QQ4ADjKLm3m+jninECVISln2aoTaQ== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Tue, 1 Sep 2020 19:51:04 +0800 Message-Id: <20200901115113.1529675-33-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:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v1 33/42] net/txgbe: add EEPROM info get 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 EEPROM information get related operations. Signed-off-by: Jiawen Wu --- drivers/net/txgbe/base/txgbe_eeprom.h | 8 ++ drivers/net/txgbe/base/txgbe_hw.c | 137 +++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_hw.h | 5 + drivers/net/txgbe/base/txgbe_phy.c | 16 +++ drivers/net/txgbe/base/txgbe_phy.h | 3 + drivers/net/txgbe/txgbe_ethdev.c | 154 ++++++++++++++++++++++++++ 6 files changed, 323 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_eeprom.h b/drivers/net/txgbe/base/txgbe_eeprom.h index 44f555bbc..34bcb3feb 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 088fa0aab..80ecec34d 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -717,6 +717,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))) { + mngsem |= swmask; + wr32(hw, TXGBE_MNGSEM, mngsem); + txgbe_release_eeprom_semaphore(hw); + return 0; + } else { + /* Resource is currently in use by FW or SW */ + txgbe_release_eeprom_semaphore(hw); + msec_delay(5); + } + } + + /* 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 @@ -1070,6 +1141,62 @@ 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 @@ -1556,8 +1683,12 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) phy->setup_link_speed = txgbe_setup_phy_link_speed; phy->read_i2c_byte = txgbe_read_i2c_byte; phy->write_i2c_byte = txgbe_write_i2c_byte; + phy->read_i2c_sff8472 = txgbe_read_i2c_sff8472; phy->read_i2c_eeprom = txgbe_read_i2c_eeprom; phy->write_i2c_eeprom = txgbe_write_i2c_eeprom; + phy->identify_sfp = txgbe_identify_module; + phy->read_i2c_byte_unlocked = txgbe_read_i2c_byte_unlocked; + phy->write_i2c_byte_unlocked = txgbe_write_i2c_byte_unlocked; phy->reset = txgbe_reset_phy; /* MAC */ @@ -1567,6 +1698,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; @@ -1576,6 +1709,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; @@ -1590,6 +1724,9 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) mac->get_link_capabilities = txgbe_get_link_capabilities_raptor; mac->check_link = txgbe_check_mac_link; + /* Manageability interface */ + mac->set_fw_drv_ver = txgbe_hic_set_drv_ver; + /* EEPROM */ rom->init_params = txgbe_init_eeprom_params; rom->read16 = txgbe_ee_read16; diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index 61bbb5e0a..a5ee3ec0a 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -33,6 +33,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); @@ -42,6 +44,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_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 7981fb2f8..e9b096df9 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1178,6 +1178,22 @@ s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, eeprom_data); } +/** + * txgbe_read_i2c_sff8472 - Reads 8 bit word over I2C interface + * @hw: pointer to hardware structure + * @byte_offset: byte offset at address 0xA2 + * @sff8472_data: value read + * + * Performs byte read operation to SFP module's SFF-8472 data over I2C + **/ +s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, + u8 *sff8472_data) +{ + return hw->phy.read_i2c_byte(hw, byte_offset, + TXGBE_I2C_EEPROM_DEV_ADDR2, + sff8472_data); +} + /** * txgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index fbef67e78..33afa367a 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -354,6 +354,7 @@ s32 txgbe_setup_phy_link_tnx(struct txgbe_hw *hw); s32 txgbe_identify_module(struct txgbe_hw *hw); s32 txgbe_identify_sfp_module(struct txgbe_hw *hw); s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw); + s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, @@ -362,6 +363,8 @@ s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); +s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, + u8 *sff8472_data); s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index f5a986309..ba2849a82 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -313,6 +313,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) { @@ -379,6 +402,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); @@ -941,6 +967,8 @@ txgbe_dev_close(struct rte_eth_dev *dev) dev->rx_pkt_burst = NULL; dev->tx_pkt_burst = NULL; + /* Unlock any pending hardware semaphore */ + txgbe_swfw_lock_reset(hw); /* disable uio intr before callback unregister */ rte_intr_disable(intr_handle); @@ -2149,6 +2177,127 @@ txgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, txgbe_dev_addr_list_itr, TRUE); } +static int +txgbe_get_eeprom_length(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + + /* Return unit is byte count */ + return hw->rom.word_size * 2; +} + +static int +txgbe_get_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *in_eeprom) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_rom_info *eeprom = &hw->rom; + uint16_t *data = in_eeprom->data; + int first, length; + + first = in_eeprom->offset >> 1; + length = in_eeprom->length >> 1; + if ((first > hw->rom.word_size) || + ((first + length) > hw->rom.word_size)) + return -EINVAL; + + in_eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + return eeprom->readw_buffer(hw, first, length, data); +} + +static int +txgbe_set_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *in_eeprom) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_rom_info *eeprom = &hw->rom; + uint16_t *data = in_eeprom->data; + int first, length; + + first = in_eeprom->offset >> 1; + length = in_eeprom->length >> 1; + if ((first > hw->rom.word_size) || + ((first + length) > hw->rom.word_size)) + return -EINVAL; + + in_eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + return eeprom->writew_buffer(hw, first, length, data); +} + +static int +txgbe_get_module_info(struct rte_eth_dev *dev, + struct rte_eth_dev_module_info *modinfo) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t status; + uint8_t sff8472_rev, addr_mode; + bool page_swap = false; + + /* Check whether we support SFF-8472 or not */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_COMP, + &sff8472_rev); + if (status != 0) + return -EIO; + + /* addressing mode is not supported */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_SWAP, + &addr_mode); + if (status != 0) + return -EIO; + + if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { + PMD_DRV_LOG(ERR, + "Address change required to access page 0xA2, " + "but not supported. Please report the module " + "type to the driver maintainers."); + page_swap = true; + } + + if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap) { + /* We have a SFP, but it does not support SFF-8472 */ + modinfo->type = RTE_ETH_MODULE_SFF_8079; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + } else { + /* We have a SFP which supports a revision of SFF-8472. */ + modinfo->type = RTE_ETH_MODULE_SFF_8472; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + } + + return 0; +} + +static int +txgbe_get_module_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *info) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t status = TXGBE_ERR_PHY_ADDR_INVALID; + uint8_t databyte = 0xFF; + uint8_t *data = info->data; + uint32_t i = 0; + + if (info->length == 0) + return -EINVAL; + + for (i = info->offset; i < info->offset + info->length; i++) { + if (i < RTE_ETH_MODULE_SFF_8079_LEN) + status = hw->phy.read_i2c_eeprom(hw, i, &databyte); + else + status = hw->phy.read_i2c_sff8472(hw, i, &databyte); + + if (status != 0) + return -EIO; + + data[i - info->offset] = databyte; + } + + return 0; +} + static const struct eth_dev_ops txgbe_eth_dev_ops = { .dev_start = txgbe_dev_start, .dev_stop = txgbe_dev_stop, @@ -2182,6 +2331,11 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = { .mac_addr_remove = txgbe_remove_rar, .mac_addr_set = txgbe_set_default_mac_addr, .set_mc_addr_list = txgbe_dev_set_mc_addr_list, + .get_eeprom_length = txgbe_get_eeprom_length, + .get_eeprom = txgbe_get_eeprom, + .set_eeprom = txgbe_set_eeprom, + .get_module_info = txgbe_get_module_info, + .get_module_eeprom = txgbe_get_module_eeprom, }; RTE_PMD_REGISTER_PCI(net_txgbe, rte_txgbe_pmd); -- 2.18.4