diff --git a/drivers/net/ngbe/base/ngbe_eeprom.h b/drivers/net/ngbe/base/ngbe_eeprom.h index 26ac686723c..68c4296b500 100644 --- a/drivers/net/ngbe/base/ngbe_eeprom.h +++ b/drivers/net/ngbe/base/ngbe_eeprom.h @@ -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); diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index 0f1a5b9f8d7..e8dda8d4603 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -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]; diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index b9805af4995..26a7ff4e83a 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -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_ */ diff --git a/drivers/net/ngbe/base/ngbe_mng.c b/drivers/net/ngbe/base/ngbe_mng.c index ad9372bec2e..79e8f50b039 100644 --- a/drivers/net/ngbe/base/ngbe_mng.c +++ b/drivers/net/ngbe/base/ngbe_mng.c @@ -117,21 +117,7 @@ ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer, for (bi = 0; bi < dword_len; bi++) buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); - /* - * If there is any thing in data position pull it in - * Read Flash command requires reading buffer length from - * two byes instead of one byte - */ - if (resp->cmd == 0x30) { - for (; bi < dword_len + 2; bi++) - buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); - - buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) - & 0xF00) | resp->buf_len; - hdr_size += (2 << 2); - } else { - buf_len = resp->buf_len; - } + buf_len = resp->buf_len; if (!buf_len) goto rel_out; @@ -379,3 +365,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); +} diff --git a/drivers/net/ngbe/base/ngbe_mng.h b/drivers/net/ngbe/base/ngbe_mng.h index 7dee6053f98..081ca5977a6 100644 --- a/drivers/net/ngbe/base/ngbe_mng.h +++ b/drivers/net/ngbe/base/ngbe_mng.h @@ -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_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c index 8746a72eb35..36128265fd5 100644 --- a/drivers/net/ngbe/base/ngbe_phy_mvl.c +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c @@ -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) { diff --git a/drivers/net/ngbe/base/ngbe_regs.h b/drivers/net/ngbe/base/ngbe_regs.h index c0e79a2ba79..8a6776b0e6f 100644 --- a/drivers/net/ngbe/base/ngbe_regs.h +++ b/drivers/net/ngbe/base/ngbe_regs.h @@ -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 diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 1b74b7a61f6..a987bbe25b4 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -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; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index b9618cc0747..23a452cacde 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -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;