1f501a195SJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause 2f501a195SJiawen Wu * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 3f501a195SJiawen Wu * Copyright(c) 2010-2017 Intel Corporation 4f501a195SJiawen Wu */ 5f501a195SJiawen Wu 6f501a195SJiawen Wu #include "ngbe_type.h" 7f501a195SJiawen Wu #include "ngbe_mng.h" 8f501a195SJiawen Wu 9f501a195SJiawen Wu /** 10f501a195SJiawen Wu * ngbe_hic_unlocked - Issue command to manageability block unlocked 11f501a195SJiawen Wu * @hw: pointer to the HW structure 12f501a195SJiawen Wu * @buffer: command to write and where the return status will be placed 13f501a195SJiawen Wu * @length: length of buffer, must be multiple of 4 bytes 14f501a195SJiawen Wu * @timeout: time in ms to wait for command completion 15f501a195SJiawen Wu * 16f501a195SJiawen Wu * Communicates with the manageability block. On success return 0 17f501a195SJiawen Wu * else returns semaphore error when encountering an error acquiring 18f501a195SJiawen Wu * semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 19f501a195SJiawen Wu * 20f501a195SJiawen Wu * This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held 21f501a195SJiawen Wu * by the caller. 22f501a195SJiawen Wu **/ 23f501a195SJiawen Wu static s32 24f501a195SJiawen Wu ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout) 25f501a195SJiawen Wu { 26f501a195SJiawen Wu u32 value, loop; 27f501a195SJiawen Wu u16 i, dword_len; 28f501a195SJiawen Wu 29f501a195SJiawen Wu if (!length || length > NGBE_PMMBX_BSIZE) { 30c811e6a4SJiawen Wu DEBUGOUT("Buffer length failure buffersize=%d.", length); 31f501a195SJiawen Wu return NGBE_ERR_HOST_INTERFACE_COMMAND; 32f501a195SJiawen Wu } 33f501a195SJiawen Wu 34f501a195SJiawen Wu /* Calculate length in DWORDs. We must be DWORD aligned */ 35f501a195SJiawen Wu if (length % sizeof(u32)) { 36f501a195SJiawen Wu DEBUGOUT("Buffer length failure, not aligned to dword"); 37f501a195SJiawen Wu return NGBE_ERR_INVALID_ARGUMENT; 38f501a195SJiawen Wu } 39f501a195SJiawen Wu 40f501a195SJiawen Wu dword_len = length >> 2; 41f501a195SJiawen Wu 42f501a195SJiawen Wu /* The device driver writes the relevant command block 43f501a195SJiawen Wu * into the ram area. 44f501a195SJiawen Wu */ 45f501a195SJiawen Wu for (i = 0; i < dword_len; i++) { 46f501a195SJiawen Wu wr32a(hw, NGBE_MNGMBX, i, cpu_to_le32(buffer[i])); 47f501a195SJiawen Wu buffer[i] = rd32a(hw, NGBE_MNGMBX, i); 48f501a195SJiawen Wu } 49f501a195SJiawen Wu ngbe_flush(hw); 50f501a195SJiawen Wu 51f501a195SJiawen Wu /* Setting this bit tells the ARC that a new command is pending. */ 52f501a195SJiawen Wu wr32m(hw, NGBE_MNGMBXCTL, 53f501a195SJiawen Wu NGBE_MNGMBXCTL_SWRDY, NGBE_MNGMBXCTL_SWRDY); 54f501a195SJiawen Wu 55f501a195SJiawen Wu /* Check command completion */ 56f501a195SJiawen Wu loop = po32m(hw, NGBE_MNGMBXCTL, 57f501a195SJiawen Wu NGBE_MNGMBXCTL_FWRDY, NGBE_MNGMBXCTL_FWRDY, 58f501a195SJiawen Wu &value, timeout, 1000); 59f501a195SJiawen Wu if (!loop || !(value & NGBE_MNGMBXCTL_FWACK)) { 60c811e6a4SJiawen Wu DEBUGOUT("Command has failed with no status valid."); 61f501a195SJiawen Wu return NGBE_ERR_HOST_INTERFACE_COMMAND; 62f501a195SJiawen Wu } 63f501a195SJiawen Wu 64f501a195SJiawen Wu return 0; 65f501a195SJiawen Wu } 66f501a195SJiawen Wu 67f501a195SJiawen Wu /** 68f501a195SJiawen Wu * ngbe_host_interface_command - Issue command to manageability block 69f501a195SJiawen Wu * @hw: pointer to the HW structure 70f501a195SJiawen Wu * @buffer: contains the command to write and where the return status will 71f501a195SJiawen Wu * be placed 72f501a195SJiawen Wu * @length: length of buffer, must be multiple of 4 bytes 73f501a195SJiawen Wu * @timeout: time in ms to wait for command completion 74f501a195SJiawen Wu * @return_data: read and return data from the buffer (true) or not (false) 75f501a195SJiawen Wu * Needed because FW structures are big endian and decoding of 76f501a195SJiawen Wu * these fields can be 8 bit or 16 bit based on command. Decoding 77f501a195SJiawen Wu * is not easily understood without making a table of commands. 78f501a195SJiawen Wu * So we will leave this up to the caller to read back the data 79f501a195SJiawen Wu * in these cases. 80f501a195SJiawen Wu * 81f501a195SJiawen Wu * Communicates with the manageability block. On success return 0 82f501a195SJiawen Wu * else returns semaphore error when encountering an error acquiring 83f501a195SJiawen Wu * semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 84f501a195SJiawen Wu **/ 85f501a195SJiawen Wu static s32 86f501a195SJiawen Wu ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer, 87f501a195SJiawen Wu u32 length, u32 timeout, bool return_data) 88f501a195SJiawen Wu { 89f501a195SJiawen Wu u32 hdr_size = sizeof(struct ngbe_hic_hdr); 90f501a195SJiawen Wu struct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer; 91f501a195SJiawen Wu u16 buf_len; 92f501a195SJiawen Wu s32 err; 93f501a195SJiawen Wu u32 bi; 94f501a195SJiawen Wu u32 dword_len; 95f501a195SJiawen Wu 96f501a195SJiawen Wu if (length == 0 || length > NGBE_PMMBX_BSIZE) { 97c811e6a4SJiawen Wu DEBUGOUT("Buffer length failure buffersize=%d.", length); 98f501a195SJiawen Wu return NGBE_ERR_HOST_INTERFACE_COMMAND; 99f501a195SJiawen Wu } 100f501a195SJiawen Wu 101f501a195SJiawen Wu /* Take management host interface semaphore */ 102f501a195SJiawen Wu err = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX); 103f501a195SJiawen Wu if (err) 104f501a195SJiawen Wu return err; 105f501a195SJiawen Wu 106f501a195SJiawen Wu err = ngbe_hic_unlocked(hw, buffer, length, timeout); 107f501a195SJiawen Wu if (err) 108f501a195SJiawen Wu goto rel_out; 109f501a195SJiawen Wu 110f501a195SJiawen Wu if (!return_data) 111f501a195SJiawen Wu goto rel_out; 112f501a195SJiawen Wu 113f501a195SJiawen Wu /* Calculate length in DWORDs */ 114f501a195SJiawen Wu dword_len = hdr_size >> 2; 115f501a195SJiawen Wu 116f501a195SJiawen Wu /* first pull in the header so we know the buffer length */ 117f501a195SJiawen Wu for (bi = 0; bi < dword_len; bi++) 118f501a195SJiawen Wu buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); 119f501a195SJiawen Wu 120f501a195SJiawen Wu buf_len = resp->buf_len; 121f501a195SJiawen Wu if (!buf_len) 122f501a195SJiawen Wu goto rel_out; 123f501a195SJiawen Wu 124f501a195SJiawen Wu if (length < buf_len + hdr_size) { 125c811e6a4SJiawen Wu DEBUGOUT("Buffer not large enough for reply message."); 126f501a195SJiawen Wu err = NGBE_ERR_HOST_INTERFACE_COMMAND; 127f501a195SJiawen Wu goto rel_out; 128f501a195SJiawen Wu } 129f501a195SJiawen Wu 130f501a195SJiawen Wu /* Calculate length in DWORDs, add 3 for odd lengths */ 131f501a195SJiawen Wu dword_len = (buf_len + 3) >> 2; 132f501a195SJiawen Wu 133f501a195SJiawen Wu /* Pull in the rest of the buffer (bi is where we left off) */ 134f501a195SJiawen Wu for (; bi <= dword_len; bi++) 135f501a195SJiawen Wu buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); 136f501a195SJiawen Wu 137f501a195SJiawen Wu rel_out: 138f501a195SJiawen Wu hw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX); 139f501a195SJiawen Wu 140f501a195SJiawen Wu return err; 141f501a195SJiawen Wu } 142f501a195SJiawen Wu 143506abd4aSJiawen Wu /** 144506abd4aSJiawen Wu * ngbe_hic_sr_read - Read EEPROM word using a host interface cmd 145506abd4aSJiawen Wu * assuming that the semaphore is already obtained. 146506abd4aSJiawen Wu * @hw: pointer to hardware structure 147506abd4aSJiawen Wu * @offset: offset of word in the EEPROM to read 148506abd4aSJiawen Wu * @data: word read from the EEPROM 149506abd4aSJiawen Wu * 150506abd4aSJiawen Wu * Reads a 16 bit word from the EEPROM using the hostif. 151506abd4aSJiawen Wu **/ 152506abd4aSJiawen Wu s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len) 153506abd4aSJiawen Wu { 154506abd4aSJiawen Wu struct ngbe_hic_read_shadow_ram command; 155506abd4aSJiawen Wu u32 value; 156506abd4aSJiawen Wu int err, i = 0, j = 0; 157506abd4aSJiawen Wu 158506abd4aSJiawen Wu if (len > NGBE_PMMBX_DATA_SIZE) 159506abd4aSJiawen Wu return NGBE_ERR_HOST_INTERFACE_COMMAND; 160506abd4aSJiawen Wu 161506abd4aSJiawen Wu memset(&command, 0, sizeof(command)); 162506abd4aSJiawen Wu command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 163506abd4aSJiawen Wu command.hdr.req.buf_lenh = 0; 164506abd4aSJiawen Wu command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 165506abd4aSJiawen Wu command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 166506abd4aSJiawen Wu command.address = cpu_to_be32(addr); 167506abd4aSJiawen Wu command.length = cpu_to_be16(len); 168506abd4aSJiawen Wu 169506abd4aSJiawen Wu err = ngbe_hic_unlocked(hw, (u32 *)&command, 170506abd4aSJiawen Wu sizeof(command), NGBE_HI_COMMAND_TIMEOUT); 171506abd4aSJiawen Wu if (err) 172506abd4aSJiawen Wu return err; 173506abd4aSJiawen Wu 174506abd4aSJiawen Wu while (i < (len >> 2)) { 175506abd4aSJiawen Wu value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 176506abd4aSJiawen Wu ((u32 *)buf)[i] = value; 177506abd4aSJiawen Wu i++; 178506abd4aSJiawen Wu } 179506abd4aSJiawen Wu 180506abd4aSJiawen Wu value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 181506abd4aSJiawen Wu for (i <<= 2; i < len; i++) 182506abd4aSJiawen Wu ((u8 *)buf)[i] = ((u8 *)&value)[j++]; 183506abd4aSJiawen Wu 184506abd4aSJiawen Wu return 0; 185506abd4aSJiawen Wu } 186506abd4aSJiawen Wu 1879459ea29SJiawen Wu /** 1889459ea29SJiawen Wu * ngbe_hic_sr_write - Write EEPROM word using hostif 1899459ea29SJiawen Wu * @hw: pointer to hardware structure 1909459ea29SJiawen Wu * @offset: offset of word in the EEPROM to write 1919459ea29SJiawen Wu * @data: word write to the EEPROM 1929459ea29SJiawen Wu * 1939459ea29SJiawen Wu * Write a 16 bit word to the EEPROM using the hostif. 1949459ea29SJiawen Wu **/ 1959459ea29SJiawen Wu s32 ngbe_hic_sr_write(struct ngbe_hw *hw, u32 addr, u8 *buf, int len) 1969459ea29SJiawen Wu { 1979459ea29SJiawen Wu struct ngbe_hic_write_shadow_ram command; 1989459ea29SJiawen Wu u32 value; 1999459ea29SJiawen Wu int err = 0, i = 0, j = 0; 2009459ea29SJiawen Wu 2019459ea29SJiawen Wu if (len > NGBE_PMMBX_DATA_SIZE) 2029459ea29SJiawen Wu return NGBE_ERR_HOST_INTERFACE_COMMAND; 2039459ea29SJiawen Wu 2049459ea29SJiawen Wu memset(&command, 0, sizeof(command)); 2059459ea29SJiawen Wu command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 2069459ea29SJiawen Wu command.hdr.req.buf_lenh = 0; 2079459ea29SJiawen Wu command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 2089459ea29SJiawen Wu command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 2099459ea29SJiawen Wu command.address = cpu_to_be32(addr); 2109459ea29SJiawen Wu command.length = cpu_to_be16(len); 2119459ea29SJiawen Wu 2129459ea29SJiawen Wu while (i < (len >> 2)) { 2139459ea29SJiawen Wu value = ((u32 *)buf)[i]; 2149459ea29SJiawen Wu wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value); 2159459ea29SJiawen Wu i++; 2169459ea29SJiawen Wu } 2179459ea29SJiawen Wu 2189459ea29SJiawen Wu for (i <<= 2; i < len; i++) 2199459ea29SJiawen Wu ((u8 *)&value)[j++] = ((u8 *)buf)[i]; 2209459ea29SJiawen Wu 2219459ea29SJiawen Wu wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value); 2229459ea29SJiawen Wu 2239459ea29SJiawen Wu UNREFERENCED_PARAMETER(&command); 2249459ea29SJiawen Wu 2259459ea29SJiawen Wu return err; 2269459ea29SJiawen Wu } 2279459ea29SJiawen Wu 228ac6c5e9aSJiawen Wu s32 ngbe_hic_pcie_read(struct ngbe_hw *hw, u16 addr, u32 *buf, int len) 229ac6c5e9aSJiawen Wu { 230ac6c5e9aSJiawen Wu struct ngbe_hic_read_pcie command; 231ac6c5e9aSJiawen Wu u32 value = 0; 232ac6c5e9aSJiawen Wu int err, i = 0; 233ac6c5e9aSJiawen Wu 234ac6c5e9aSJiawen Wu if (len > NGBE_PMMBX_DATA_SIZE) 235ac6c5e9aSJiawen Wu return NGBE_ERR_HOST_INTERFACE_COMMAND; 236ac6c5e9aSJiawen Wu 237ac6c5e9aSJiawen Wu memset(&command, 0, sizeof(command)); 238ac6c5e9aSJiawen Wu command.hdr.cmd = FW_PCIE_READ_CMD; 239ac6c5e9aSJiawen Wu command.hdr.buf_len = sizeof(command) - sizeof(command.hdr); 240ac6c5e9aSJiawen Wu command.hdr.checksum = FW_DEFAULT_CHECKSUM; 241ac6c5e9aSJiawen Wu command.lan_id = hw->bus.lan_id; 242ac6c5e9aSJiawen Wu command.addr = addr; 243ac6c5e9aSJiawen Wu 244ac6c5e9aSJiawen Wu err = ngbe_host_interface_command(hw, (u32 *)&command, 245ac6c5e9aSJiawen Wu sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false); 246ac6c5e9aSJiawen Wu if (err) 247ac6c5e9aSJiawen Wu return err; 248ac6c5e9aSJiawen Wu 249ac6c5e9aSJiawen Wu while (i < (len >> 2)) { 250ac6c5e9aSJiawen Wu value = rd32a(hw, NGBE_MNGMBX, FW_PCIE_BUSMASTER_OFFSET + i); 251ac6c5e9aSJiawen Wu ((u32 *)buf)[i] = value; 252ac6c5e9aSJiawen Wu i++; 253ac6c5e9aSJiawen Wu } 254ac6c5e9aSJiawen Wu 255ac6c5e9aSJiawen Wu return 0; 256ac6c5e9aSJiawen Wu } 257ac6c5e9aSJiawen Wu 258ac6c5e9aSJiawen Wu s32 ngbe_hic_pcie_write(struct ngbe_hw *hw, u16 addr, u32 *buf, int len) 259ac6c5e9aSJiawen Wu { 260ac6c5e9aSJiawen Wu struct ngbe_hic_write_pcie command; 261ac6c5e9aSJiawen Wu u32 value = 0; 262ac6c5e9aSJiawen Wu int err, i = 0; 263ac6c5e9aSJiawen Wu 264ac6c5e9aSJiawen Wu while (i < (len >> 2)) { 265ac6c5e9aSJiawen Wu value = ((u32 *)buf)[i]; 266ac6c5e9aSJiawen Wu i++; 267ac6c5e9aSJiawen Wu } 268ac6c5e9aSJiawen Wu 269ac6c5e9aSJiawen Wu memset(&command, 0, sizeof(command)); 270ac6c5e9aSJiawen Wu command.hdr.cmd = FW_PCIE_WRITE_CMD; 271ac6c5e9aSJiawen Wu command.hdr.buf_len = sizeof(command) - sizeof(command.hdr); 272ac6c5e9aSJiawen Wu command.hdr.checksum = FW_DEFAULT_CHECKSUM; 273ac6c5e9aSJiawen Wu command.lan_id = hw->bus.lan_id; 274ac6c5e9aSJiawen Wu command.addr = addr; 275ac6c5e9aSJiawen Wu command.data = value; 276ac6c5e9aSJiawen Wu 277ac6c5e9aSJiawen Wu err = ngbe_host_interface_command(hw, (u32 *)&command, 278ac6c5e9aSJiawen Wu sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false); 279ac6c5e9aSJiawen Wu if (err) 280ac6c5e9aSJiawen Wu return err; 281ac6c5e9aSJiawen Wu 282ac6c5e9aSJiawen Wu return 0; 283ac6c5e9aSJiawen Wu } 284ac6c5e9aSJiawen Wu 285f501a195SJiawen Wu s32 ngbe_hic_check_cap(struct ngbe_hw *hw) 286f501a195SJiawen Wu { 287f501a195SJiawen Wu struct ngbe_hic_read_shadow_ram command; 288f501a195SJiawen Wu s32 err; 289f501a195SJiawen Wu int i; 290f501a195SJiawen Wu 291f501a195SJiawen Wu command.hdr.req.cmd = FW_EEPROM_CHECK_STATUS; 292f501a195SJiawen Wu command.hdr.req.buf_lenh = 0; 293f501a195SJiawen Wu command.hdr.req.buf_lenl = 0; 294f501a195SJiawen Wu command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 295f501a195SJiawen Wu 296f501a195SJiawen Wu /* convert offset from words to bytes */ 297f501a195SJiawen Wu command.address = 0; 298f501a195SJiawen Wu /* one word */ 299f501a195SJiawen Wu command.length = 0; 300f501a195SJiawen Wu 301f501a195SJiawen Wu for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 302f501a195SJiawen Wu err = ngbe_host_interface_command(hw, (u32 *)&command, 303f501a195SJiawen Wu sizeof(command), 304f501a195SJiawen Wu NGBE_HI_COMMAND_TIMEOUT, true); 305f501a195SJiawen Wu if (err) 306f501a195SJiawen Wu continue; 307f501a195SJiawen Wu 308f501a195SJiawen Wu command.hdr.rsp.ret_status &= 0x1F; 309f501a195SJiawen Wu if (command.hdr.rsp.ret_status != 310f501a195SJiawen Wu FW_CEM_RESP_STATUS_SUCCESS) 311f501a195SJiawen Wu err = NGBE_ERR_HOST_INTERFACE_COMMAND; 312f501a195SJiawen Wu 313f501a195SJiawen Wu break; 314f501a195SJiawen Wu } 315f501a195SJiawen Wu 316f501a195SJiawen Wu if (!err && command.address != FW_CHECKSUM_CAP_ST_PASS) 317f501a195SJiawen Wu err = NGBE_ERR_EEPROM_CHECKSUM; 318f501a195SJiawen Wu 319f501a195SJiawen Wu return err; 320f501a195SJiawen Wu } 321fbd5ceb0SJiawen Wu 322fbd5ceb0SJiawen Wu s32 ngbe_phy_led_oem_chk(struct ngbe_hw *hw, u32 *data) 323fbd5ceb0SJiawen Wu { 324fbd5ceb0SJiawen Wu struct ngbe_hic_read_shadow_ram command; 325fbd5ceb0SJiawen Wu s32 err; 326fbd5ceb0SJiawen Wu int i; 327fbd5ceb0SJiawen Wu 328fbd5ceb0SJiawen Wu command.hdr.req.cmd = FW_PHY_LED_CONF; 329fbd5ceb0SJiawen Wu command.hdr.req.buf_lenh = 0; 330fbd5ceb0SJiawen Wu command.hdr.req.buf_lenl = 0; 331fbd5ceb0SJiawen Wu command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 332fbd5ceb0SJiawen Wu 333fbd5ceb0SJiawen Wu /* convert offset from words to bytes */ 334fbd5ceb0SJiawen Wu command.address = 0; 335fbd5ceb0SJiawen Wu /* one word */ 336fbd5ceb0SJiawen Wu command.length = 0; 337fbd5ceb0SJiawen Wu 338fbd5ceb0SJiawen Wu for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 339fbd5ceb0SJiawen Wu err = ngbe_host_interface_command(hw, (u32 *)&command, 340fbd5ceb0SJiawen Wu sizeof(command), 341fbd5ceb0SJiawen Wu NGBE_HI_COMMAND_TIMEOUT, true); 342fbd5ceb0SJiawen Wu if (err) 343fbd5ceb0SJiawen Wu continue; 344fbd5ceb0SJiawen Wu 345fbd5ceb0SJiawen Wu command.hdr.rsp.ret_status &= 0x1F; 346fbd5ceb0SJiawen Wu if (command.hdr.rsp.ret_status != 347fbd5ceb0SJiawen Wu FW_CEM_RESP_STATUS_SUCCESS) 348fbd5ceb0SJiawen Wu err = NGBE_ERR_HOST_INTERFACE_COMMAND; 349fbd5ceb0SJiawen Wu 350fbd5ceb0SJiawen Wu break; 351fbd5ceb0SJiawen Wu } 352fbd5ceb0SJiawen Wu 353fbd5ceb0SJiawen Wu if (err) 354fbd5ceb0SJiawen Wu return err; 355fbd5ceb0SJiawen Wu 356fbd5ceb0SJiawen Wu if (command.address == FW_CHECKSUM_CAP_ST_PASS) { 357fbd5ceb0SJiawen Wu *data = ((u32 *)&command)[2]; 358fbd5ceb0SJiawen Wu err = 0; 359fbd5ceb0SJiawen Wu } else if (command.address == FW_CHECKSUM_CAP_ST_FAIL) { 360fbd5ceb0SJiawen Wu *data = FW_CHECKSUM_CAP_ST_FAIL; 361fbd5ceb0SJiawen Wu err = -1; 362fbd5ceb0SJiawen Wu } else { 363fbd5ceb0SJiawen Wu err = NGBE_ERR_EEPROM_CHECKSUM; 364fbd5ceb0SJiawen Wu } 365fbd5ceb0SJiawen Wu 366fbd5ceb0SJiawen Wu return err; 367fbd5ceb0SJiawen Wu } 368*91e64c0eSJiawen Wu 369*91e64c0eSJiawen Wu s32 ngbe_hic_get_lldp(struct ngbe_hw *hw) 370*91e64c0eSJiawen Wu { 371*91e64c0eSJiawen Wu struct ngbe_hic_write_lldp buffer; 372*91e64c0eSJiawen Wu s32 err = 0; 373*91e64c0eSJiawen Wu 374*91e64c0eSJiawen Wu buffer.hdr.cmd = FW_LLDP_GET_CMD; 375*91e64c0eSJiawen Wu buffer.hdr.buf_len = 0x1; 376*91e64c0eSJiawen Wu buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 377*91e64c0eSJiawen Wu buffer.hdr.checksum = FW_DEFAULT_CHECKSUM; 378*91e64c0eSJiawen Wu buffer.func = hw->bus.lan_id; 379*91e64c0eSJiawen Wu 380*91e64c0eSJiawen Wu err = ngbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer), 381*91e64c0eSJiawen Wu NGBE_HI_COMMAND_TIMEOUT, true); 382*91e64c0eSJiawen Wu if (err) 383*91e64c0eSJiawen Wu return err; 384*91e64c0eSJiawen Wu 385*91e64c0eSJiawen Wu if (buffer.hdr.cmd_or_resp.ret_status == FW_CEM_RESP_STATUS_SUCCESS) { 386*91e64c0eSJiawen Wu /* this field returns the status of LLDP */ 387*91e64c0eSJiawen Wu if (buffer.func) 388*91e64c0eSJiawen Wu hw->lldp_enabled = true; 389*91e64c0eSJiawen Wu else 390*91e64c0eSJiawen Wu hw->lldp_enabled = false; 391*91e64c0eSJiawen Wu } else { 392*91e64c0eSJiawen Wu err = NGBE_ERR_HOST_INTERFACE_COMMAND; 393*91e64c0eSJiawen Wu } 394*91e64c0eSJiawen Wu 395*91e64c0eSJiawen Wu return err; 396*91e64c0eSJiawen Wu } 397*91e64c0eSJiawen Wu 398*91e64c0eSJiawen Wu s32 ngbe_hic_set_lldp(struct ngbe_hw *hw, bool on) 399*91e64c0eSJiawen Wu { 400*91e64c0eSJiawen Wu struct ngbe_hic_write_lldp buffer; 401*91e64c0eSJiawen Wu 402*91e64c0eSJiawen Wu if (on) 403*91e64c0eSJiawen Wu buffer.hdr.cmd = FW_LLDP_SET_CMD_ON; 404*91e64c0eSJiawen Wu else 405*91e64c0eSJiawen Wu buffer.hdr.cmd = FW_LLDP_SET_CMD_OFF; 406*91e64c0eSJiawen Wu buffer.hdr.buf_len = 0x1; 407*91e64c0eSJiawen Wu buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 408*91e64c0eSJiawen Wu buffer.hdr.checksum = FW_DEFAULT_CHECKSUM; 409*91e64c0eSJiawen Wu buffer.func = hw->bus.lan_id; 410*91e64c0eSJiawen Wu 411*91e64c0eSJiawen Wu return ngbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer), 412*91e64c0eSJiawen Wu NGBE_HI_COMMAND_TIMEOUT, false); 413*91e64c0eSJiawen Wu } 414