@@ -11,6 +11,10 @@
#define NGBE_CALSUM_CAP_STATUS 0x10224
#define NGBE_EEPROM_VERSION_STORE_REG 0x1022C
+#define NGBE_FW_SUPPORT_LLDP 0x19
+#define NGBE_FW_GET_LLDP 0x1B
+#define NGBE_FW_MASK 0xFF
+
s32 ngbe_init_eeprom_params(struct ngbe_hw *hw);
s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw, u16 *checksum_val);
s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw);
@@ -10,6 +10,56 @@
#include "ngbe_mng.h"
#include "ngbe_hw.h"
+static s32 ngbe_is_lldp(struct ngbe_hw *hw)
+{
+ u32 tmp = 0, lldp_flash_data = 0, i;
+ s32 err = 0;
+
+ if ((hw->eeprom_id & NGBE_FW_MASK) >= NGBE_FW_GET_LLDP) {
+ err = ngbe_hic_get_lldp(hw);
+ if (err == 0)
+ return 0;
+ }
+
+ for (i = 0; i < 1024; i++) {
+ err = ngbe_flash_read_dword(hw, NGBE_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 ngbe_disable_lldp(struct ngbe_hw *hw)
+{
+ s32 err = 0;
+
+ if ((hw->eeprom_id & NGBE_FW_MASK) < NGBE_FW_SUPPORT_LLDP)
+ return;
+
+ err = ngbe_is_lldp(hw);
+ if (err) {
+ PMD_INIT_LOG(INFO, "Can not get LLDP status.");
+ } else if (hw->lldp_enabled) {
+ err = ngbe_hic_set_lldp(hw, false);
+ if (!err)
+ 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.");
+ }
+}
+
/**
* ngbe_start_hw - Prepare hardware for Tx/Rx
* @hw: pointer to hardware structure
@@ -55,6 +105,7 @@ s32 ngbe_init_hw(struct ngbe_hw *hw)
ngbe_read_efuse(hw);
ngbe_save_eeprom_version(hw);
+ ngbe_disable_lldp(hw);
/* Reset the hardware */
status = hw->mac.reset_hw(hw);
@@ -1816,9 +1867,9 @@ s32 ngbe_enable_rx_dma(struct ngbe_hw *hw, u32 regval)
* 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 NGBE_ERR_TIMEOUT on failure.
*/
-u32 ngbe_fmgr_cmd_op(struct ngbe_hw *hw, u32 cmd, u32 cmd_addr)
+s32 ngbe_fmgr_cmd_op(struct ngbe_hw *hw, u32 cmd, u32 cmd_addr)
{
u32 cmd_val, i;
@@ -1832,33 +1883,35 @@ u32 ngbe_fmgr_cmd_op(struct ngbe_hw *hw, u32 cmd, u32 cmd_addr)
usec_delay(10);
}
if (i == NGBE_SPI_TIMEOUT)
- return 1;
+ return NGBE_ERR_TIMEOUT;
return 0;
}
-u32 ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr)
+s32 ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr, u32 *data)
{
- u32 status;
+ s32 status;
status = ngbe_fmgr_cmd_op(hw, 1, addr);
- if (status == 0x1) {
+ if (status < 0) {
DEBUGOUT("Read flash timeout.");
return status;
}
- return rd32(hw, NGBE_SPIDAT);
+ *data = rd32(hw, NGBE_SPIDAT);
+
+ return 0;
}
void ngbe_read_efuse(struct ngbe_hw *hw)
{
- u32 efuse[2];
+ u32 efuse[2] = {0, 0};
u8 lan_id = hw->bus.lan_id;
- efuse[0] = ngbe_flash_read_dword(hw, 0xfe010 + lan_id * 8);
- efuse[1] = ngbe_flash_read_dword(hw, 0xfe010 + lan_id * 8 + 4);
+ ngbe_flash_read_dword(hw, 0xfe010 + lan_id * 8, &efuse[0]);
+ ngbe_flash_read_dword(hw, 0xfe010 + lan_id * 8 + 4, &efuse[1]);
- DEBUGOUT("port %d efuse[0] = %08x, efuse[1] = %08x\n",
+ DEBUGOUT("port %d efuse[0] = %08x, efuse[1] = %08x",
lan_id, efuse[0], efuse[1]);
hw->gphy_efuse[0] = efuse[0];
@@ -84,8 +84,8 @@ s32 ngbe_enable_rx_dma(struct ngbe_hw *hw, u32 regval);
void ngbe_map_device_id(struct ngbe_hw *hw);
void ngbe_read_efuse(struct ngbe_hw *hw);
-u32 ngbe_fmgr_cmd_op(struct ngbe_hw *hw, u32 cmd, u32 cmd_addr);
-u32 ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr);
+s32 ngbe_fmgr_cmd_op(struct ngbe_hw *hw, u32 cmd, u32 cmd_addr);
+s32 ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr, u32 *data);
void ngbe_set_ncsi_status(struct ngbe_hw *hw);
#endif /* _NGBE_HW_H_ */
@@ -379,3 +379,49 @@ s32 ngbe_phy_led_oem_chk(struct ngbe_hw *hw, u32 *data)
return err;
}
+
+s32 ngbe_hic_get_lldp(struct ngbe_hw *hw)
+{
+ struct ngbe_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 = ngbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
+ NGBE_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 = NGBE_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ return err;
+}
+
+s32 ngbe_hic_set_lldp(struct ngbe_hw *hw, bool on)
+{
+ struct ngbe_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 ngbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
+ NGBE_HI_COMMAND_TIMEOUT, false);
+}
@@ -28,6 +28,10 @@
#define FW_EEPROM_CHECK_STATUS 0xE9
#define FW_PHY_LED_CONF 0xF1
#define FW_READ_SHADOW_RAM_GPIO 0xB4
+#define FW_LLDP_GET_CMD 0xF5
+#define FW_LLDP_SET_CMD_OFF 0xF3
+#define FW_LLDP_SET_CMD_ON 0xF2
+#define FW_CEM_CMD_RESERVED 0X0
#define FW_CHECKSUM_CAP_ST_PASS 0x80658383
#define FW_CHECKSUM_CAP_ST_FAIL 0x70657376
@@ -97,6 +101,13 @@ struct ngbe_hic_write_pcie {
u32 data;
};
+struct ngbe_hic_write_lldp {
+ struct ngbe_hic_hdr hdr;
+ u8 func;
+ u8 pad2;
+ u16 pad3;
+};
+
s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len);
s32 ngbe_hic_sr_write(struct ngbe_hw *hw, u32 addr, u8 *buf, int len);
s32 ngbe_hic_pcie_read(struct ngbe_hw *hw, u16 addr, u32 *buf, int len);
@@ -104,5 +115,7 @@ s32 ngbe_hic_pcie_write(struct ngbe_hw *hw, u16 addr, u32 *buf, int len);
s32 ngbe_hic_check_cap(struct ngbe_hw *hw);
s32 ngbe_phy_led_oem_chk(struct ngbe_hw *hw, u32 *data);
+s32 ngbe_hic_get_lldp(struct ngbe_hw *hw);
+s32 ngbe_hic_set_lldp(struct ngbe_hw *hw, bool on);
#endif /* _NGBE_MNG_H_ */
@@ -53,7 +53,7 @@ s32 ngbe_check_phy_mode_mvl(struct ngbe_hw *hw)
u8 value = 0;
u32 phy_mode = 0;
- phy_mode = ngbe_flash_read_dword(hw, 0xFF010);
+ ngbe_flash_read_dword(hw, 0xFF010, &phy_mode);
value = (u8)(phy_mode >> (hw->bus.lan_id * 8));
if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_COPPER) {
@@ -1257,6 +1257,8 @@ enum ngbe_5tuple_protocol {
#define NGBE_MDIOMODE_PRT1CL22 MS(1, 0x1)
#define NGBE_MDIOMODE_PRT0CL22 MS(0, 0x1)
+#define NGBE_LLDP_REG 0x0F1000
+
#define NVM_OROM_OFFSET 0x17
#define NVM_OROM_BLK_LOW 0x83
#define NVM_OROM_BLK_HI 0x84
@@ -455,10 +455,12 @@ struct ngbe_hw {
u16 sub_device_id;
u16 sub_system_id;
u32 eeprom_id;
+ u8 port_id;
u8 revision_id;
bool adapter_stopped;
bool wol_enabled;
bool ncsi_enabled;
+ bool lldp_enabled;
uint64_t isb_dma;
void IOMEM *isb_mem;
@@ -371,15 +371,16 @@ eth_ngbe_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->sub_system_id = pci_dev->id.subsystem_device_id;
} else {
- u32 ssid;
+ u32 ssid = 0;
- ssid = ngbe_flash_read_dword(hw, 0xFFFDC);
- if (ssid == 0x1) {
+ err = ngbe_flash_read_dword(hw, 0xFFFDC, &ssid);
+ if (err) {
PMD_INIT_LOG(ERR,
"Read of internal subsystem device id failed\n");
return -ENODEV;