@@ -12,6 +12,9 @@
#define TXGBE_FW_VER_LEN 32
#define TXGBE_FW_N_TXEQ 0x0002000A
+#define TXGBE_FW_SUPPORT_LLDP 0x0F
+#define TXGBE_FW_GET_LLDP 0x11
+#define TXGBE_FW_MASK 0xFF
#define TXGBE_FW_PTR 0x0F
#define TXGBE_PBANUM0_PTR 0x05
@@ -27,6 +27,56 @@ static s32 txgbe_mta_vector(struct txgbe_hw *hw, u8 *mc_addr);
static s32 txgbe_get_san_mac_addr_offset(struct txgbe_hw *hw,
u16 *san_mac_offset);
+static s32 txgbe_is_lldp(struct txgbe_hw *hw)
+{
+ u32 tmp = 0, lldp_flash_data = 0, i;
+ s32 err = 0;
+
+ if ((hw->fw_version & TXGBE_FW_MASK) >= TXGBE_FW_GET_LLDP) {
+ err = txgbe_hic_get_lldp(hw);
+ if (err == 0)
+ return 0;
+ }
+
+ for (i = 0; i < 1024; i++) {
+ err = txgbe_flash_read_dword(hw, TXGBE_LLDP_REG + i * 4, &tmp);
+ if (err)
+ return err;
+
+ if (tmp == BIT_MASK32)
+ break;
+ lldp_flash_data = tmp;
+ }
+
+ if (lldp_flash_data & MS(hw->bus.lan_id, 1))
+ hw->lldp_enabled = true;
+ else
+ hw->lldp_enabled = false;
+
+ return 0;
+}
+
+static void txgbe_disable_lldp(struct txgbe_hw *hw)
+{
+ s32 status = 0;
+
+ if ((hw->fw_version & TXGBE_FW_MASK) < TXGBE_FW_SUPPORT_LLDP)
+ return;
+
+ status = txgbe_is_lldp(hw);
+ if (status) {
+ PMD_INIT_LOG(INFO, "Can not get LLDP status.");
+ } else if (hw->lldp_enabled) {
+ status = txgbe_hic_set_lldp(hw, false);
+ if (!status)
+ PMD_INIT_LOG(INFO,
+ "LLDP detected on port %d, turn it off by default.",
+ hw->port_id);
+ else
+ PMD_INIT_LOG(INFO, "Can not set LLDP status.");
+ }
+}
+
/**
* txgbe_device_supports_autoneg_fc - Check if device supports autonegotiation
* of flow control
@@ -272,6 +322,8 @@ s32 txgbe_init_hw(struct txgbe_hw *hw)
/* Get firmware version */
hw->phy.get_fw_version(hw, &hw->fw_version);
+ txgbe_disable_lldp(hw);
+
/* Reset the hardware */
status = hw->mac.reset_hw(hw);
if (status == 0 || status == TXGBE_ERR_SFP_NOT_PRESENT) {
@@ -2668,9 +2720,9 @@ s32 txgbe_prot_autoc_write_raptor(struct txgbe_hw *hw, bool locked, u64 autoc)
* 1. to be sector address, when implemented erase sector command
* 2. to be flash address when implemented read, write flash address
*
- * Return 0 on success, return 1 on failure.
+ * Return 0 on success, return TXGBE_ERR_TIMEOUT on failure.
*/
-u32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr)
+s32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr)
{
u32 cmd_val, i;
@@ -2685,22 +2737,24 @@ u32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr)
}
if (i == TXGBE_SPI_TIMEOUT)
- return 1;
+ return TXGBE_ERR_TIMEOUT;
return 0;
}
-u32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr)
+s32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr, u32 *data)
{
- u32 status;
+ s32 status;
status = txgbe_fmgr_cmd_op(hw, 1, addr);
- if (status == 0x1) {
+ if (status < 0) {
DEBUGOUT("Read flash timeout.");
return status;
}
- return rd32(hw, TXGBE_SPIDAT);
+ *data = rd32(hw, TXGBE_SPIDAT);
+
+ return 0;
}
/**
@@ -112,6 +112,6 @@ s32 txgbe_prot_autoc_read_raptor(struct txgbe_hw *hw, bool *locked, u64 *value);
s32 txgbe_prot_autoc_write_raptor(struct txgbe_hw *hw, bool locked, u64 value);
s32 txgbe_reinit_fdir_tables(struct txgbe_hw *hw);
bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw);
-u32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr);
-u32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr);
+s32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr);
+s32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr, u32 *data);
#endif /* _TXGBE_HW_H_ */
@@ -439,3 +439,49 @@ txgbe_mng_enabled(struct txgbe_hw *hw)
/* firmware does not control laser */
return false;
}
+
+s32 txgbe_hic_get_lldp(struct txgbe_hw *hw)
+{
+ struct txgbe_hic_write_lldp buffer;
+ s32 err = 0;
+
+ buffer.hdr.cmd = FW_LLDP_GET_CMD;
+ buffer.hdr.buf_len = 0x1;
+ buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+ buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
+ buffer.func = hw->bus.lan_id;
+
+ err = txgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
+ TXGBE_HI_COMMAND_TIMEOUT, true);
+ if (err)
+ return err;
+
+ if (buffer.hdr.cmd_or_resp.ret_status == FW_CEM_RESP_STATUS_SUCCESS) {
+ /* this field returns the status of LLDP */
+ if (buffer.func)
+ hw->lldp_enabled = true;
+ else
+ hw->lldp_enabled = false;
+ } else {
+ err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ return err;
+}
+
+s32 txgbe_hic_set_lldp(struct txgbe_hw *hw, bool on)
+{
+ struct txgbe_hic_write_lldp buffer;
+
+ if (on)
+ buffer.hdr.cmd = FW_LLDP_SET_CMD_ON;
+ else
+ buffer.hdr.cmd = FW_LLDP_SET_CMD_OFF;
+ buffer.hdr.buf_len = 0x1;
+ buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+ buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
+ buffer.func = hw->bus.lan_id;
+
+ return txgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
+ TXGBE_HI_COMMAND_TIMEOUT, false);
+}
@@ -53,6 +53,9 @@
#define FW_PHY_TOKEN_RETRIES ((FW_PHY_TOKEN_WAIT * 1000) / FW_PHY_TOKEN_DELAY)
#define FW_DW_OPEN_NOTIFY 0xE9
#define FW_DW_CLOSE_NOTIFY 0xEA
+#define FW_LLDP_GET_CMD 0xF2
+#define FW_LLDP_SET_CMD_OFF 0xF1
+#define FW_LLDP_SET_CMD_ON 0xF0
#define TXGBE_CHECKSUM_CAP_ST_PASS 0x80658383
#define TXGBE_CHECKSUM_CAP_ST_FAIL 0x70657376
@@ -171,6 +174,13 @@ struct txgbe_hic_upg_verify {
u32 action_flag;
};
+struct txgbe_hic_write_lldp {
+ struct txgbe_hic_hdr hdr;
+ u8 func;
+ u8 pad2;
+ u16 pad3;
+};
+
s32 txgbe_hic_sr_read(struct txgbe_hw *hw, u32 addr, u8 *buf, int len);
s32 txgbe_hic_sr_write(struct txgbe_hw *hw, u32 addr, u8 *buf, int len);
s32 txgbe_close_notify(struct txgbe_hw *hw);
@@ -181,4 +191,7 @@ s32 txgbe_hic_set_drv_ver(struct txgbe_hw *hw, u8 maj, u8 min, u8 build,
s32 txgbe_hic_reset(struct txgbe_hw *hw);
bool txgbe_mng_present(struct txgbe_hw *hw);
bool txgbe_mng_enabled(struct txgbe_hw *hw);
+s32 txgbe_hic_get_lldp(struct txgbe_hw *hw);
+s32 txgbe_hic_set_lldp(struct txgbe_hw *hw, bool on);
+
#endif /* _TXGBE_MNG_H_ */
@@ -1684,6 +1684,8 @@ enum txgbe_5tuple_protocol {
#define TXGBE_ISBADDRL 0x000160
#define TXGBE_ISBADDRH 0x000164
+#define TXGBE_LLDP_REG 0x0F1000
+
#define NVM_OROM_OFFSET 0x17
#define NVM_OROM_BLK_LOW 0x83
#define NVM_OROM_BLK_HI 0x84
@@ -778,10 +778,12 @@ struct txgbe_hw {
u16 vendor_id;
u16 subsystem_device_id;
u16 subsystem_vendor_id;
+ u8 port_id;
u8 revision_id;
bool adapter_stopped;
int api_version;
bool allow_unsupported_sfp;
+ bool lldp_enabled;
bool need_crosstalk_fix;
bool dev_start;
bool autoneg;
@@ -602,15 +602,16 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
/* Vendor and Device ID need to be set before init of shared code */
hw->back = pci_dev;
+ hw->port_id = eth_dev->data->port_id;
hw->device_id = pci_dev->id.device_id;
hw->vendor_id = pci_dev->id.vendor_id;
if (pci_dev->id.subsystem_vendor_id == PCI_VENDOR_ID_WANGXUN) {
hw->subsystem_device_id = pci_dev->id.subsystem_device_id;
} else {
- u32 ssid;
+ u32 ssid = 0;
- ssid = txgbe_flash_read_dword(hw, 0xFFFDC);
- if (ssid == 0x1) {
+ err = txgbe_flash_read_dword(hw, 0xFFFDC, &ssid);
+ if (err) {
PMD_INIT_LOG(ERR,
"Read of internal subsystem device id failed\n");
return -ENODEV;