1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2015-2020 3 */ 4 5 #include "txgbe_type.h" 6 #include "txgbe_mng.h" 7 8 /** 9 * txgbe_calculate_checksum - Calculate checksum for buffer 10 * @buffer: pointer to EEPROM 11 * @length: size of EEPROM to calculate a checksum for 12 * Calculates the checksum for some buffer on a specified length. The 13 * checksum calculated is returned. 14 **/ 15 static u8 16 txgbe_calculate_checksum(u8 *buffer, u32 length) 17 { 18 u32 i; 19 u8 sum = 0; 20 21 for (i = 0; i < length; i++) 22 sum += buffer[i]; 23 24 return (u8)(0 - sum); 25 } 26 27 /** 28 * txgbe_hic_unlocked - Issue command to manageability block unlocked 29 * @hw: pointer to the HW structure 30 * @buffer: command to write and where the return status will be placed 31 * @length: length of buffer, must be multiple of 4 bytes 32 * @timeout: time in ms to wait for command completion 33 * 34 * Communicates with the manageability block. On success return 0 35 * else returns semaphore error when encountering an error acquiring 36 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 37 * 38 * This function assumes that the TXGBE_MNGSEM_SWMBX semaphore is held 39 * by the caller. 40 **/ 41 static s32 42 txgbe_hic_unlocked(struct txgbe_hw *hw, u32 *buffer, u32 length, u32 timeout) 43 { 44 u32 value, loop; 45 u16 i, dword_len; 46 47 DEBUGFUNC("txgbe_hic_unlocked"); 48 49 if (!length || length > TXGBE_PMMBX_BSIZE) { 50 DEBUGOUT("Buffer length failure buffersize=%d.\n", length); 51 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 52 } 53 54 /* Calculate length in DWORDs. We must be DWORD aligned */ 55 if (length % sizeof(u32)) { 56 DEBUGOUT("Buffer length failure, not aligned to dword"); 57 return TXGBE_ERR_INVALID_ARGUMENT; 58 } 59 60 dword_len = length >> 2; 61 62 /* The device driver writes the relevant command block 63 * into the ram area. 64 */ 65 for (i = 0; i < dword_len; i++) { 66 wr32a(hw, TXGBE_MNGMBX, i, cpu_to_le32(buffer[i])); 67 buffer[i] = rd32a(hw, TXGBE_MNGMBX, i); 68 } 69 txgbe_flush(hw); 70 71 /* Setting this bit tells the ARC that a new command is pending. */ 72 wr32m(hw, TXGBE_MNGMBXCTL, 73 TXGBE_MNGMBXCTL_SWRDY, TXGBE_MNGMBXCTL_SWRDY); 74 75 /* Check command completion */ 76 loop = po32m(hw, TXGBE_MNGMBXCTL, 77 TXGBE_MNGMBXCTL_FWRDY, TXGBE_MNGMBXCTL_FWRDY, 78 &value, timeout, 1000); 79 if (!loop || !(value & TXGBE_MNGMBXCTL_FWACK)) { 80 DEBUGOUT("Command has failed with no status valid.\n"); 81 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 82 } 83 84 return 0; 85 } 86 87 /** 88 * txgbe_host_interface_command - Issue command to manageability block 89 * @hw: pointer to the HW structure 90 * @buffer: contains the command to write and where the return status will 91 * be placed 92 * @length: length of buffer, must be multiple of 4 bytes 93 * @timeout: time in ms to wait for command completion 94 * @return_data: read and return data from the buffer (true) or not (false) 95 * Needed because FW structures are big endian and decoding of 96 * these fields can be 8 bit or 16 bit based on command. Decoding 97 * is not easily understood without making a table of commands. 98 * So we will leave this up to the caller to read back the data 99 * in these cases. 100 * 101 * Communicates with the manageability block. On success return 0 102 * else returns semaphore error when encountering an error acquiring 103 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 104 **/ 105 static s32 106 txgbe_host_interface_command(struct txgbe_hw *hw, u32 *buffer, 107 u32 length, u32 timeout, bool return_data) 108 { 109 u32 hdr_size = sizeof(struct txgbe_hic_hdr); 110 struct txgbe_hic_hdr *resp = (struct txgbe_hic_hdr *)buffer; 111 u16 buf_len; 112 s32 err; 113 u32 bi; 114 u32 dword_len; 115 116 DEBUGFUNC("txgbe_host_interface_command"); 117 118 if (length == 0 || length > TXGBE_PMMBX_BSIZE) { 119 DEBUGOUT("Buffer length failure buffersize=%d.\n", length); 120 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 121 } 122 123 /* Take management host interface semaphore */ 124 err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWMBX); 125 if (err) 126 return err; 127 128 err = txgbe_hic_unlocked(hw, buffer, length, timeout); 129 if (err) 130 goto rel_out; 131 132 if (!return_data) 133 goto rel_out; 134 135 /* Calculate length in DWORDs */ 136 dword_len = hdr_size >> 2; 137 138 /* first pull in the header so we know the buffer length */ 139 for (bi = 0; bi < dword_len; bi++) 140 buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi); 141 142 /* 143 * If there is any thing in data position pull it in 144 * Read Flash command requires reading buffer length from 145 * two byes instead of one byte 146 */ 147 if (resp->cmd == 0x30) { 148 for (; bi < dword_len + 2; bi++) 149 buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi); 150 151 buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) 152 & 0xF00) | resp->buf_len; 153 hdr_size += (2 << 2); 154 } else { 155 buf_len = resp->buf_len; 156 } 157 if (!buf_len) 158 goto rel_out; 159 160 if (length < buf_len + hdr_size) { 161 DEBUGOUT("Buffer not large enough for reply message.\n"); 162 err = TXGBE_ERR_HOST_INTERFACE_COMMAND; 163 goto rel_out; 164 } 165 166 /* Calculate length in DWORDs, add 3 for odd lengths */ 167 dword_len = (buf_len + 3) >> 2; 168 169 /* Pull in the rest of the buffer (bi is where we left off) */ 170 for (; bi <= dword_len; bi++) 171 buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi); 172 173 rel_out: 174 hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWMBX); 175 176 return err; 177 } 178 179 /** 180 * txgbe_hic_sr_read - Read EEPROM word using a host interface cmd 181 * assuming that the semaphore is already obtained. 182 * @hw: pointer to hardware structure 183 * @offset: offset of word in the EEPROM to read 184 * @data: word read from the EEPROM 185 * 186 * Reads a 16 bit word from the EEPROM using the hostif. 187 **/ 188 s32 txgbe_hic_sr_read(struct txgbe_hw *hw, u32 addr, u8 *buf, int len) 189 { 190 struct txgbe_hic_read_shadow_ram command; 191 u32 value; 192 int err, i = 0, j = 0; 193 194 if (len > TXGBE_PMMBX_DATA_SIZE) 195 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 196 197 memset(&command, 0, sizeof(command)); 198 command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 199 command.hdr.req.buf_lenh = 0; 200 command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 201 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 202 command.address = cpu_to_be32(addr); 203 command.length = cpu_to_be16(len); 204 205 err = txgbe_hic_unlocked(hw, (u32 *)&command, 206 sizeof(command), TXGBE_HI_COMMAND_TIMEOUT); 207 if (err) 208 return err; 209 210 while (i < (len >> 2)) { 211 value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 212 ((u32 *)buf)[i] = value; 213 i++; 214 } 215 216 value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 217 for (i <<= 2; i < len; i++) 218 ((u8 *)buf)[i] = ((u8 *)&value)[j++]; 219 220 return 0; 221 } 222 223 /** 224 * txgbe_hic_sr_write - Write EEPROM word using hostif 225 * @hw: pointer to hardware structure 226 * @offset: offset of word in the EEPROM to write 227 * @data: word write to the EEPROM 228 * 229 * Write a 16 bit word to the EEPROM using the hostif. 230 **/ 231 s32 txgbe_hic_sr_write(struct txgbe_hw *hw, u32 addr, u8 *buf, int len) 232 { 233 struct txgbe_hic_write_shadow_ram command; 234 u32 value; 235 int err = 0, i = 0, j = 0; 236 237 if (len > TXGBE_PMMBX_DATA_SIZE) 238 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 239 240 memset(&command, 0, sizeof(command)); 241 command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 242 command.hdr.req.buf_lenh = 0; 243 command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 244 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 245 command.address = cpu_to_be32(addr); 246 command.length = cpu_to_be16(len); 247 248 while (i < (len >> 2)) { 249 value = ((u32 *)buf)[i]; 250 wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value); 251 i++; 252 } 253 254 for (i <<= 2; i < len; i++) 255 ((u8 *)&value)[j++] = ((u8 *)buf)[i]; 256 257 wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value); 258 259 UNREFERENCED_PARAMETER(&command); 260 261 return err; 262 } 263 264 /** 265 * txgbe_hic_set_drv_ver - Sends driver version to firmware 266 * @hw: pointer to the HW structure 267 * @maj: driver version major number 268 * @min: driver version minor number 269 * @build: driver version build number 270 * @sub: driver version sub build number 271 * @len: unused 272 * @driver_ver: unused 273 * 274 * Sends driver version number to firmware through the manageability 275 * block. On success return 0 276 * else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring 277 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 278 **/ 279 s32 txgbe_hic_set_drv_ver(struct txgbe_hw *hw, u8 maj, u8 min, 280 u8 build, u8 sub, u16 len, 281 const char *driver_ver) 282 { 283 struct txgbe_hic_drv_info fw_cmd; 284 int i; 285 s32 ret_val = 0; 286 287 DEBUGFUNC("txgbe_hic_set_drv_ver"); 288 UNREFERENCED_PARAMETER(len, driver_ver); 289 290 fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 291 fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 292 fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 293 fw_cmd.port_num = (u8)hw->bus.func; 294 fw_cmd.ver_maj = maj; 295 fw_cmd.ver_min = min; 296 fw_cmd.ver_build = build; 297 fw_cmd.ver_sub = sub; 298 fw_cmd.hdr.checksum = 0; 299 fw_cmd.pad = 0; 300 fw_cmd.pad2 = 0; 301 fw_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&fw_cmd, 302 (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 303 304 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 305 ret_val = txgbe_host_interface_command(hw, (u32 *)&fw_cmd, 306 sizeof(fw_cmd), 307 TXGBE_HI_COMMAND_TIMEOUT, 308 true); 309 if (ret_val != 0) 310 continue; 311 312 if (fw_cmd.hdr.cmd_or_resp.ret_status == 313 FW_CEM_RESP_STATUS_SUCCESS) 314 ret_val = 0; 315 else 316 ret_val = TXGBE_ERR_HOST_INTERFACE_COMMAND; 317 318 break; 319 } 320 321 return ret_val; 322 } 323 324 /** 325 * txgbe_hic_reset - send reset cmd to fw 326 * @hw: pointer to hardware structure 327 * 328 * Sends reset cmd to firmware through the manageability 329 * block. On success return 0 330 * else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring 331 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 332 **/ 333 s32 334 txgbe_hic_reset(struct txgbe_hw *hw) 335 { 336 struct txgbe_hic_reset reset_cmd; 337 int i; 338 s32 err = 0; 339 340 DEBUGFUNC("\n"); 341 342 reset_cmd.hdr.cmd = FW_RESET_CMD; 343 reset_cmd.hdr.buf_len = FW_RESET_LEN; 344 reset_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 345 reset_cmd.lan_id = hw->bus.lan_id; 346 reset_cmd.reset_type = (u16)hw->reset_type; 347 reset_cmd.hdr.checksum = 0; 348 reset_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&reset_cmd, 349 (FW_CEM_HDR_LEN + reset_cmd.hdr.buf_len)); 350 351 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 352 err = txgbe_host_interface_command(hw, (u32 *)&reset_cmd, 353 sizeof(reset_cmd), 354 TXGBE_HI_COMMAND_TIMEOUT, 355 true); 356 if (err != 0) 357 continue; 358 359 if (reset_cmd.hdr.cmd_or_resp.ret_status == 360 FW_CEM_RESP_STATUS_SUCCESS) 361 err = 0; 362 else 363 err = TXGBE_ERR_HOST_INTERFACE_COMMAND; 364 365 break; 366 } 367 368 return err; 369 } 370 371 /** 372 * txgbe_mng_present - returns true when management capability is present 373 * @hw: pointer to hardware structure 374 */ 375 bool 376 txgbe_mng_present(struct txgbe_hw *hw) 377 { 378 if (hw->mac.type == txgbe_mac_unknown) 379 return false; 380 381 return !!rd32m(hw, TXGBE_STAT, TXGBE_STAT_MNGINIT); 382 } 383 384 /** 385 * txgbe_mng_enabled - Is the manageability engine enabled? 386 * @hw: pointer to hardware structure 387 * 388 * Returns true if the manageability engine is enabled. 389 **/ 390 bool 391 txgbe_mng_enabled(struct txgbe_hw *hw) 392 { 393 UNREFERENCED_PARAMETER(hw); 394 /* firmware does not control laser */ 395 return false; 396 } 397