1 /*- 2 * Copyright (c) 2017 Broadcom. All rights reserved. 3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /** 33 * @defgroup sli SLI-4 Base APIs 34 */ 35 36 /** 37 * @file 38 * All common (i.e. transport-independent) SLI-4 functions are implemented 39 * in this file. 40 */ 41 42 #include "sli4.h" 43 44 #if defined(OCS_INCLUDE_DEBUG) 45 #include "ocs_utils.h" 46 #endif 47 48 #define SLI4_BMBX_DELAY_US 1000 /* 1 ms */ 49 #define SLI4_INIT_PORT_DELAY_US 10000 /* 10 ms */ 50 51 static int32_t sli_fw_init(sli4_t *); 52 static int32_t sli_fw_term(sli4_t *); 53 static int32_t sli_sliport_control(sli4_t *sli4, uint32_t endian); 54 static int32_t sli_cmd_fw_deinitialize(sli4_t *, void *, size_t); 55 static int32_t sli_cmd_fw_initialize(sli4_t *, void *, size_t); 56 static int32_t sli_queue_doorbell(sli4_t *, sli4_queue_t *); 57 static uint8_t sli_queue_entry_is_valid(sli4_queue_t *, uint8_t *, uint8_t); 58 59 const uint8_t sli4_fw_initialize[] = { 60 0xff, 0x12, 0x34, 0xff, 61 0xff, 0x56, 0x78, 0xff, 62 }; 63 64 const uint8_t sli4_fw_deinitialize[] = { 65 0xff, 0xaa, 0xbb, 0xff, 66 0xff, 0xcc, 0xdd, 0xff, 67 }; 68 69 typedef struct { 70 uint32_t rev_id; 71 uint32_t family; /* generation */ 72 sli4_asic_type_e type; 73 sli4_asic_rev_e rev; 74 } sli4_asic_entry_t; 75 76 sli4_asic_entry_t sli4_asic_table[] = { 77 { 0x00, 1, SLI4_ASIC_TYPE_BE3, SLI4_ASIC_REV_A0}, 78 { 0x01, 1, SLI4_ASIC_TYPE_BE3, SLI4_ASIC_REV_A1}, 79 { 0x02, 1, SLI4_ASIC_TYPE_BE3, SLI4_ASIC_REV_A2}, 80 { 0x00, 4, SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_A0}, 81 { 0x00, 2, SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_A0}, 82 { 0x10, 1, SLI4_ASIC_TYPE_BE3, SLI4_ASIC_REV_B0}, 83 { 0x10, 0x04, SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_B0}, 84 { 0x11, 0x04, SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_B1}, 85 { 0x0, 0x0a, SLI4_ASIC_TYPE_LANCER, SLI4_ASIC_REV_A0}, 86 { 0x10, 0x0b, SLI4_ASIC_TYPE_LANCER, SLI4_ASIC_REV_B0}, 87 { 0x30, 0x0b, SLI4_ASIC_TYPE_LANCER, SLI4_ASIC_REV_D0}, 88 { 0x3, 0x0b, SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3}, 89 { 0x0, 0x0c, SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A0}, 90 { 0x1, 0x0c, SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A1}, 91 { 0x3, 0x0c, SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3}, 92 { 0x1, 0x0d, SLI4_ASIC_TYPE_LANCERG7,SLI4_ASIC_REV_A1}, 93 { 0x10, 0x0d, SLI4_ASIC_TYPE_LANCERG7,SLI4_ASIC_REV_B0}, 94 { 0x00, 0x05, SLI4_ASIC_TYPE_CORSAIR, SLI4_ASIC_REV_A0}, 95 }; 96 97 /* 98 * @brief Convert queue type enum (SLI_QTYPE_*) into a string. 99 */ 100 const char *SLI_QNAME[] = { 101 "Event Queue", 102 "Completion Queue", 103 "Mailbox Queue", 104 "Work Queue", 105 "Receive Queue", 106 "Undefined" 107 }; 108 109 /** 110 * @brief Define the mapping of registers to their BAR and offset. 111 * 112 * @par Description 113 * Although SLI-4 specification defines a common set of registers, their locations 114 * (both BAR and offset) depend on the interface type. This array maps a register 115 * enum to an array of BAR/offset pairs indexed by the interface type. For 116 * example, to access the bootstrap mailbox register on an interface type 0 117 * device, code can refer to the offset using regmap[SLI4_REG_BMBX][0].offset. 118 * 119 * @b Note: A value of UINT32_MAX for either the register set (rset) or offset (off) 120 * indicates an invalid mapping. 121 */ 122 const sli4_reg_t regmap[SLI4_REG_MAX][SLI4_MAX_IF_TYPES] = { 123 /* SLI4_REG_BMBX */ 124 { 125 { 2, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, 126 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX } , { 0, SLI4_BMBX_REG }, 127 }, 128 /* SLI4_REG_EQCQ_DOORBELL */ 129 { 130 { 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG }, 131 { 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG }, 132 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 133 { 1, SLI4_IF6_EQ_DOORBELL_REG } 134 }, 135 // SLI4_REG_CQ_DOORBELL 136 { 137 { 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG }, 138 { 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG }, 139 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 140 { 1, SLI4_IF6_CQ_DOORBELL_REG } 141 }, 142 /* SLI4_REG_FCOE_RQ_DOORBELL */ 143 { 144 { 2, SLI4_RQ_DOORBELL_REG }, { 0, SLI4_RQ_DOORBELL_REG }, 145 { 0, SLI4_RQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX }, 146 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 147 { 1, SLI4_IF6_RQ_DOORBELL_REG } 148 }, 149 /* SLI4_REG_IO_WQ_DOORBELL */ 150 { 151 { 2, SLI4_IO_WQ_DOORBELL_REG }, { 0, SLI4_IO_WQ_DOORBELL_REG }, 152 { 0, SLI4_IO_WQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX }, 153 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 154 { 1, SLI4_IF6_WQ_DOORBELL_REG } 155 }, 156 /* SLI4_REG_MQ_DOORBELL */ 157 { 158 { 2, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG }, 159 { 0, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG }, 160 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 161 { 1, SLI4_IF6_MQ_DOORBELL_REG } 162 }, 163 /* SLI4_REG_PHYSDEV_CONTROL */ 164 { 165 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 166 { 0, SLI4_PHSDEV_CONTROL_REG_236 }, { 0, SLI4_PHSDEV_CONTROL_REG_236 }, 167 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 168 { 0, SLI4_PHSDEV_CONTROL_REG_236 } 169 }, 170 /* SLI4_REG_SLIPORT_CONTROL */ 171 { 172 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 173 { 0, SLI4_SLIPORT_CONTROL_REG }, { UINT32_MAX, UINT32_MAX }, 174 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 175 { 0, SLI4_SLIPORT_CONTROL_REG }, 176 }, 177 /* SLI4_REG_SLIPORT_ERROR1 */ 178 { 179 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 180 { 0, SLI4_SLIPORT_ERROR1 }, { UINT32_MAX, UINT32_MAX }, 181 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 182 { 0, SLI4_SLIPORT_ERROR1 }, 183 }, 184 /* SLI4_REG_SLIPORT_ERROR2 */ 185 { 186 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 187 { 0, SLI4_SLIPORT_ERROR2 }, { UINT32_MAX, UINT32_MAX }, 188 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 189 { 0, SLI4_SLIPORT_ERROR2 }, 190 }, 191 /* SLI4_REG_SLIPORT_SEMAPHORE */ 192 { 193 { 1, SLI4_PORT_SEMAPHORE_REG_0 }, { 0, SLI4_PORT_SEMAPHORE_REG_1 }, 194 { 0, SLI4_PORT_SEMAPHORE_REG_236 }, { 0, SLI4_PORT_SEMAPHORE_REG_236 }, 195 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 196 { 0, SLI4_PORT_SEMAPHORE_REG_236 }, 197 }, 198 /* SLI4_REG_SLIPORT_STATUS */ 199 { 200 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 201 { 0, SLI4_PORT_STATUS_REG_236 }, { 0, SLI4_PORT_STATUS_REG_236 }, 202 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 203 { 0, SLI4_PORT_STATUS_REG_236 }, 204 }, 205 /* SLI4_REG_UERR_MASK_HI */ 206 { 207 { 0, SLI4_UERR_MASK_HIGH_REG }, { UINT32_MAX, UINT32_MAX }, 208 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 209 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 210 { UINT32_MAX, UINT32_MAX } 211 }, 212 /* SLI4_REG_UERR_MASK_LO */ 213 { 214 { 0, SLI4_UERR_MASK_LOW_REG }, { UINT32_MAX, UINT32_MAX }, 215 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 216 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 217 { UINT32_MAX, UINT32_MAX } 218 }, 219 /* SLI4_REG_UERR_STATUS_HI */ 220 { 221 { 0, SLI4_UERR_STATUS_HIGH_REG }, { UINT32_MAX, UINT32_MAX }, 222 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 223 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 224 { UINT32_MAX, UINT32_MAX } 225 }, 226 /* SLI4_REG_UERR_STATUS_LO */ 227 { 228 { 0, SLI4_UERR_STATUS_LOW_REG }, { UINT32_MAX, UINT32_MAX }, 229 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 230 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 231 { UINT32_MAX, UINT32_MAX } 232 }, 233 /* SLI4_REG_SW_UE_CSR1 */ 234 { 235 { 1, SLI4_SW_UE_CSR1}, { UINT32_MAX, UINT32_MAX }, 236 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 237 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 238 { UINT32_MAX, UINT32_MAX } 239 }, 240 /* SLI4_REG_SW_UE_CSR2 */ 241 { 242 { 1, SLI4_SW_UE_CSR2}, { UINT32_MAX, UINT32_MAX }, 243 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 244 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 245 { UINT32_MAX, UINT32_MAX } 246 }, 247 }; 248 249 /** 250 * @brief Read the given SLI register. 251 * 252 * @param sli Pointer to the SLI context. 253 * @param reg Register name enum. 254 * 255 * @return Returns the register value. 256 */ 257 uint32_t 258 sli_reg_read(sli4_t *sli, sli4_regname_e reg) 259 { 260 const sli4_reg_t *r = &(regmap[reg][sli->if_type]); 261 262 if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) { 263 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type); 264 return UINT32_MAX; 265 } 266 267 return ocs_reg_read32(sli->os, r->rset, r->off); 268 } 269 270 /** 271 * @brief Write the value to the given SLI register. 272 * 273 * @param sli Pointer to the SLI context. 274 * @param reg Register name enum. 275 * @param val Value to write. 276 * 277 * @return None. 278 */ 279 void 280 sli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val) 281 { 282 const sli4_reg_t *r = &(regmap[reg][sli->if_type]); 283 284 if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) { 285 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type); 286 return; 287 } 288 289 ocs_reg_write32(sli->os, r->rset, r->off, val); 290 } 291 292 /** 293 * @brief Check if the SLI_INTF register is valid. 294 * 295 * @param val 32-bit SLI_INTF register value. 296 * 297 * @return Returns 0 on success, or a non-zero value on failure. 298 */ 299 static uint8_t 300 sli_intf_valid_check(uint32_t val) 301 { 302 return ((val >> SLI4_INTF_VALID_SHIFT) & SLI4_INTF_VALID_MASK) != SLI4_INTF_VALID; 303 } 304 305 /** 306 * @brief Retrieve the SLI revision level. 307 * 308 * @param val 32-bit SLI_INTF register value. 309 * 310 * @return Returns the SLI revision level. 311 */ 312 static uint8_t 313 sli_intf_sli_revision(uint32_t val) 314 { 315 return ((val >> SLI4_INTF_SLI_REVISION_SHIFT) & SLI4_INTF_SLI_REVISION_MASK); 316 } 317 318 static uint8_t 319 sli_intf_sli_family(uint32_t val) 320 { 321 return ((val >> SLI4_INTF_SLI_FAMILY_SHIFT) & SLI4_INTF_SLI_FAMILY_MASK); 322 } 323 324 /** 325 * @brief Retrieve the SLI interface type. 326 * 327 * @param val 32-bit SLI_INTF register value. 328 * 329 * @return Returns the SLI interface type. 330 */ 331 static uint8_t 332 sli_intf_if_type(uint32_t val) 333 { 334 return ((val >> SLI4_INTF_IF_TYPE_SHIFT) & SLI4_INTF_IF_TYPE_MASK); 335 } 336 337 /** 338 * @brief Retrieve PCI revision ID. 339 * 340 * @param val 32-bit PCI CLASS_REVISION register value. 341 * 342 * @return Returns the PCI revision ID. 343 */ 344 static uint8_t 345 sli_pci_rev_id(uint32_t val) 346 { 347 return ((val >> SLI4_PCI_REV_ID_SHIFT) & SLI4_PCI_REV_ID_MASK); 348 } 349 350 /** 351 * @brief retrieve SLI ASIC generation 352 * 353 * @param val 32-bit SLI_ASIC_ID register value 354 * 355 * @return SLI ASIC generation 356 */ 357 static uint8_t 358 sli_asic_gen(uint32_t val) 359 { 360 return ((val >> SLI4_ASIC_GEN_SHIFT) & SLI4_ASIC_GEN_MASK); 361 } 362 363 /** 364 * @brief Wait for the bootstrap mailbox to report "ready". 365 * 366 * @param sli4 SLI context pointer. 367 * @param msec Number of milliseconds to wait. 368 * 369 * @return Returns 0 if BMBX is ready, or non-zero otherwise (i.e. time out occurred). 370 */ 371 static int32_t 372 sli_bmbx_wait(sli4_t *sli4, uint32_t msec) 373 { 374 uint32_t val = 0; 375 376 do { 377 ocs_udelay(SLI4_BMBX_DELAY_US); 378 val = sli_reg_read(sli4, SLI4_REG_BMBX); 379 msec--; 380 } while(msec && !(val & SLI4_BMBX_RDY)); 381 382 return(!(val & SLI4_BMBX_RDY)); 383 } 384 385 /** 386 * @brief Write bootstrap mailbox. 387 * 388 * @param sli4 SLI context pointer. 389 * 390 * @return Returns 0 if command succeeded, or non-zero otherwise. 391 */ 392 static int32_t 393 sli_bmbx_write(sli4_t *sli4) 394 { 395 uint32_t val = 0; 396 397 /* write buffer location to bootstrap mailbox register */ 398 ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_PREWRITE); 399 val = SLI4_BMBX_WRITE_HI(sli4->bmbx.phys); 400 sli_reg_write(sli4, SLI4_REG_BMBX, val); 401 402 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) { 403 ocs_log_crit(sli4->os, "BMBX WRITE_HI failed\n"); 404 return -1; 405 } 406 val = SLI4_BMBX_WRITE_LO(sli4->bmbx.phys); 407 sli_reg_write(sli4, SLI4_REG_BMBX, val); 408 409 /* wait for SLI Port to set ready bit */ 410 return sli_bmbx_wait(sli4, SLI4_BMBX_TIMEOUT_MSEC/*XXX*/); 411 } 412 413 #if defined(OCS_INCLUDE_DEBUG) 414 /** 415 * @ingroup sli 416 * @brief Dump BMBX mailbox command. 417 * 418 * @par Description 419 * Convenience function for dumping BMBX mailbox commands. Takes 420 * into account which mailbox command is given since SLI_CONFIG 421 * commands are special. 422 * 423 * @b Note: This function takes advantage of 424 * the one-command-at-a-time nature of the BMBX to be able to 425 * display non-embedded SLI_CONFIG commands. This will not work 426 * for mailbox commands on the MQ. Luckily, all current non-emb 427 * mailbox commands go through the BMBX. 428 * 429 * @param sli4 SLI context pointer. 430 * @param mbx Pointer to mailbox command to dump. 431 * @param prefix Prefix for dump label. 432 * 433 * @return None. 434 */ 435 static void 436 sli_dump_bmbx_command(sli4_t *sli4, void *mbx, const char *prefix) 437 { 438 uint32_t size = 0; 439 char label[64]; 440 uint32_t i; 441 /* Mailbox diagnostic logging */ 442 sli4_mbox_command_header_t *hdr = (sli4_mbox_command_header_t *)mbx; 443 444 if (!ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP)) { 445 return; 446 } 447 448 if (hdr->command == SLI4_MBOX_COMMAND_SLI_CONFIG) { 449 sli4_cmd_sli_config_t *sli_config = (sli4_cmd_sli_config_t *)hdr; 450 sli4_req_hdr_t *sli_config_hdr; 451 if (sli_config->emb) { 452 ocs_snprintf(label, sizeof(label), "%s (emb)", prefix); 453 454 /* if embedded, dump entire command */ 455 sli_config_hdr = (sli4_req_hdr_t *)sli_config->payload.embed; 456 size = sizeof(*sli_config) - sizeof(sli_config->payload) + 457 sli_config_hdr->request_length + (4*sizeof(uint32_t)); 458 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label, 459 (uint8_t *)sli4->bmbx.virt, size); 460 } else { 461 sli4_sli_config_pmd_t *pmd; 462 ocs_snprintf(label, sizeof(label), "%s (non-emb hdr)", prefix); 463 464 /* if non-embedded, break up into two parts: SLI_CONFIG hdr 465 and the payload(s) */ 466 size = sizeof(*sli_config) - sizeof(sli_config->payload) + (12 * sli_config->pmd_count); 467 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label, 468 (uint8_t *)sli4->bmbx.virt, size); 469 470 /* as sanity check, make sure first PMD matches what was saved */ 471 pmd = &sli_config->payload.mem; 472 if ((pmd->address_high == ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys)) && 473 (pmd->address_low == ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys))) { 474 for (i = 0; i < sli_config->pmd_count; i++, pmd++) { 475 sli_config_hdr = sli4->bmbx_non_emb_pmd->virt; 476 ocs_snprintf(label, sizeof(label), "%s (non-emb pay[%d])", 477 prefix, i); 478 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label, 479 (uint8_t *)sli4->bmbx_non_emb_pmd->virt, 480 sli_config_hdr->request_length + (4*sizeof(uint32_t))); 481 } 482 } else { 483 ocs_log_debug(sli4->os, "pmd addr does not match pmd:%x %x (%x %x)\n", 484 pmd->address_high, pmd->address_low, 485 ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys), 486 ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys)); 487 } 488 } 489 } else { 490 /* not an SLI_CONFIG command, just display first 64 bytes, like we do 491 for MQEs */ 492 size = 64; 493 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, prefix, 494 (uint8_t *)mbx, size); 495 } 496 } 497 #endif 498 499 /** 500 * @ingroup sli 501 * @brief Submit a command to the bootstrap mailbox and check the status. 502 * 503 * @param sli4 SLI context pointer. 504 * 505 * @return Returns 0 on success, or a non-zero value on failure. 506 */ 507 int32_t 508 sli_bmbx_command(sli4_t *sli4) 509 { 510 void *cqe = (uint8_t *)sli4->bmbx.virt + SLI4_BMBX_SIZE; 511 512 #if defined(OCS_INCLUDE_DEBUG) 513 sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmd"); 514 #endif 515 516 if (sli_fw_error_status(sli4) > 0) { 517 ocs_log_crit(sli4->os, "Chip is in an error state - Mailbox " 518 "command rejected status=%#x error1=%#x error2=%#x\n", 519 sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS), 520 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1), 521 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2)); 522 return -1; 523 } 524 525 if (sli_bmbx_write(sli4)) { 526 ocs_log_crit(sli4->os, "bootstrap mailbox write fail phys=%p reg=%#x\n", 527 (void*)sli4->bmbx.phys, 528 sli_reg_read(sli4, SLI4_REG_BMBX)); 529 return -1; 530 } 531 532 /* check completion queue entry status */ 533 ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_POSTREAD); 534 if (((sli4_mcqe_t *)cqe)->val) { 535 #if defined(OCS_INCLUDE_DEBUG) 536 sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmpl"); 537 ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "bmbx cqe", cqe, sizeof(sli4_mcqe_t)); 538 #endif 539 return sli_cqe_mq(cqe); 540 } else { 541 ocs_log_err(sli4->os, "invalid or wrong type\n"); 542 return -1; 543 } 544 } 545 546 /**************************************************************************** 547 * Messages 548 */ 549 550 /** 551 * @ingroup sli 552 * @brief Write a CONFIG_LINK command to the provided buffer. 553 * 554 * @param sli4 SLI context pointer. 555 * @param buf Virtual pointer to the destination buffer. 556 * @param size Buffer size, in bytes. 557 * 558 * @return Returns the number of bytes written. 559 */ 560 int32_t 561 sli_cmd_config_link(sli4_t *sli4, void *buf, size_t size) 562 { 563 sli4_cmd_config_link_t *config_link = buf; 564 565 ocs_memset(buf, 0, size); 566 567 config_link->hdr.command = SLI4_MBOX_COMMAND_CONFIG_LINK; 568 569 /* Port interprets zero in a field as "use default value" */ 570 571 return sizeof(sli4_cmd_config_link_t); 572 } 573 574 /** 575 * @ingroup sli 576 * @brief Write a DOWN_LINK command to the provided buffer. 577 * 578 * @param sli4 SLI context pointer. 579 * @param buf Virtual pointer to the destination buffer. 580 * @param size Buffer size, in bytes. 581 * 582 * @return Returns the number of bytes written. 583 */ 584 int32_t 585 sli_cmd_down_link(sli4_t *sli4, void *buf, size_t size) 586 { 587 sli4_mbox_command_header_t *hdr = buf; 588 589 ocs_memset(buf, 0, size); 590 591 hdr->command = SLI4_MBOX_COMMAND_DOWN_LINK; 592 593 /* Port interprets zero in a field as "use default value" */ 594 595 return sizeof(sli4_mbox_command_header_t); 596 } 597 598 /** 599 * @ingroup sli 600 * @brief Write a DUMP Type 4 command to the provided buffer. 601 * 602 * @param sli4 SLI context pointer. 603 * @param buf Virtual pointer to the destination buffer. 604 * @param size Buffer size, in bytes. 605 * @param wki The well known item ID. 606 * 607 * @return Returns the number of bytes written. 608 */ 609 int32_t 610 sli_cmd_dump_type4(sli4_t *sli4, void *buf, size_t size, uint16_t wki) 611 { 612 sli4_cmd_dump4_t *cmd = buf; 613 614 ocs_memset(buf, 0, size); 615 616 cmd->hdr.command = SLI4_MBOX_COMMAND_DUMP; 617 cmd->type = 4; 618 cmd->wki_selection = wki; 619 return sizeof(sli4_cmd_dump4_t); 620 } 621 622 /** 623 * @ingroup sli 624 * @brief Write a COMMON_READ_TRANSCEIVER_DATA command. 625 * 626 * @param sli4 SLI context. 627 * @param buf Destination buffer for the command. 628 * @param size Buffer size, in bytes. 629 * @param page_num The page of SFP data to retrieve (0xa0 or 0xa2). 630 * @param dma DMA structure from which the data will be copied. 631 * 632 * @note This creates a Version 0 message. 633 * 634 * @return Returns the number of bytes written. 635 */ 636 int32_t 637 sli_cmd_common_read_transceiver_data(sli4_t *sli4, void *buf, size_t size, uint32_t page_num, 638 ocs_dma_t *dma) 639 { 640 sli4_req_common_read_transceiver_data_t *req = NULL; 641 uint32_t sli_config_off = 0; 642 uint32_t payload_size; 643 644 if (dma == NULL) { 645 /* Payload length must accommodate both request and response */ 646 payload_size = max(sizeof(sli4_req_common_read_transceiver_data_t), 647 sizeof(sli4_res_common_read_transceiver_data_t)); 648 } else { 649 payload_size = dma->size; 650 } 651 652 if (sli4->port_type == SLI4_PORT_TYPE_FC) { 653 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, dma); 654 } 655 656 if (dma == NULL) { 657 req = (sli4_req_common_read_transceiver_data_t *)((uint8_t *)buf + sli_config_off); 658 } else { 659 req = (sli4_req_common_read_transceiver_data_t *)dma->virt; 660 ocs_memset(req, 0, dma->size); 661 } 662 663 req->hdr.opcode = SLI4_OPC_COMMON_READ_TRANSCEIVER_DATA; 664 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 665 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 666 667 req->page_number = page_num; 668 req->port = sli4->physical_port; 669 670 return(sli_config_off + sizeof(sli4_req_common_read_transceiver_data_t)); 671 } 672 673 /** 674 * @ingroup sli 675 * @brief Write a READ_LINK_STAT command to the provided buffer. 676 * 677 * @param sli4 SLI context pointer. 678 * @param buf Virtual pointer to the destination buffer. 679 * @param size Buffer size, in bytes. 680 * @param req_ext_counters If TRUE, then the extended counters will be requested. 681 * @param clear_overflow_flags If TRUE, then overflow flags will be cleared. 682 * @param clear_all_counters If TRUE, the counters will be cleared. 683 * 684 * @return Returns the number of bytes written. 685 */ 686 int32_t 687 sli_cmd_read_link_stats(sli4_t *sli4, void *buf, size_t size, 688 uint8_t req_ext_counters, 689 uint8_t clear_overflow_flags, 690 uint8_t clear_all_counters) 691 { 692 sli4_cmd_read_link_stats_t *cmd = buf; 693 694 ocs_memset(buf, 0, size); 695 696 cmd->hdr.command = SLI4_MBOX_COMMAND_READ_LNK_STAT; 697 cmd->rec = req_ext_counters; 698 cmd->clrc = clear_all_counters; 699 cmd->clof = clear_overflow_flags; 700 return sizeof(sli4_cmd_read_link_stats_t); 701 } 702 703 /** 704 * @ingroup sli 705 * @brief Write a READ_STATUS command to the provided buffer. 706 * 707 * @param sli4 SLI context pointer. 708 * @param buf Virtual pointer to the destination buffer. 709 * @param size Buffer size, in bytes. 710 * @param clear_counters If TRUE, the counters will be cleared. 711 * 712 * @return Returns the number of bytes written. 713 */ 714 int32_t 715 sli_cmd_read_status(sli4_t *sli4, void *buf, size_t size, 716 uint8_t clear_counters) 717 { 718 sli4_cmd_read_status_t *cmd = buf; 719 720 ocs_memset(buf, 0, size); 721 722 cmd->hdr.command = SLI4_MBOX_COMMAND_READ_STATUS; 723 cmd->cc = clear_counters; 724 return sizeof(sli4_cmd_read_status_t); 725 } 726 727 /** 728 * @brief Write a FW_DEINITIALIZE command to the provided buffer. 729 * 730 * @param sli4 SLI context pointer. 731 * @param buf Virtual pointer to the destination buffer. 732 * @param size Buffer size, in bytes. 733 * 734 * @return Returns the number of bytes written. 735 */ 736 static int32_t 737 sli_cmd_fw_deinitialize(sli4_t *sli4, void *buf, size_t size) 738 { 739 740 ocs_memset(buf, 0, size); 741 ocs_memcpy(buf, sli4_fw_deinitialize, sizeof(sli4_fw_deinitialize)); 742 743 return sizeof(sli4_fw_deinitialize); 744 } 745 746 /** 747 * @brief Write a FW_INITIALIZE command to the provided buffer. 748 * 749 * @param sli4 SLI context pointer. 750 * @param buf Virtual pointer to the destination buffer. 751 * @param size Buffer size, in bytes. 752 * 753 * @return Returns the number of bytes written. 754 */ 755 static int32_t 756 sli_cmd_fw_initialize(sli4_t *sli4, void *buf, size_t size) 757 { 758 759 ocs_memset(buf, 0, size); 760 ocs_memcpy(buf, sli4_fw_initialize, sizeof(sli4_fw_initialize)); 761 762 return sizeof(sli4_fw_initialize); 763 } 764 765 /** 766 * @ingroup sli 767 * @brief update INIT_LINK flags with the sli config topology. 768 * 769 * @param sli4 SLI context pointer. 770 * @param init_link Pointer to the init link command 771 * 772 * @return Returns 0 on success, -1 on failure 773 */ 774 static int32_t 775 sli4_set_link_flags_config_topo(sli4_t *sli4, sli4_cmd_init_link_t *init_link) 776 { 777 778 switch (sli4->config.topology) { 779 case SLI4_READ_CFG_TOPO_FC: 780 // Attempt P2P but failover to FC-AL 781 init_link->link_flags.enable_topology_failover = TRUE; 782 init_link->link_flags.topology = SLI4_INIT_LINK_F_P2P_FAIL_OVER; 783 break; 784 case SLI4_READ_CFG_TOPO_FC_AL: 785 init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_ONLY; 786 return (!sli_fcal_is_speed_supported(init_link->link_speed_selection_code)); 787 788 case SLI4_READ_CFG_TOPO_FC_DA: 789 init_link->link_flags.topology = FC_TOPOLOGY_P2P; 790 break; 791 default: 792 ocs_log_err(sli4->os, "unsupported topology %#x\n", sli4->config.topology); 793 return -1; 794 } 795 796 return 0; 797 } 798 799 /** 800 * @ingroup sli 801 * @brief update INIT_LINK flags with the persistent topology. 802 * PT stores value in compatible form, directly assign to link_flags 803 * 804 * @param sli4 SLI context pointer. 805 * @param init_link Pointer to the init link command 806 * 807 * @return Returns 0 on success, -1 on failure 808 */ 809 static int32_t 810 sli4_set_link_flags_persistent_topo(sli4_t *sli4, sli4_cmd_init_link_t *init_link) 811 { 812 if ((sli4->config.pt == SLI4_INIT_LINK_F_FCAL_ONLY) && 813 (!sli_fcal_is_speed_supported(init_link->link_speed_selection_code))) 814 return -1; 815 816 init_link->link_flags.enable_topology_failover = sli4->config.tf; 817 init_link->link_flags.topology = sli4->config.pt; 818 819 return 0; 820 } 821 822 /** 823 * @ingroup sli 824 * @brief Write an INIT_LINK command to the provided buffer. 825 * 826 * @param sli4 SLI context pointer. 827 * @param buf Virtual pointer to the destination buffer. 828 * @param size Buffer size, in bytes. 829 * @param speed Link speed. 830 * @param reset_alpa For native FC, this is the selective reset AL_PA 831 * 832 * @return Returns the number of bytes written. 833 */ 834 int32_t 835 sli_cmd_init_link(sli4_t *sli4, void *buf, size_t size, uint32_t speed, uint8_t reset_alpa) 836 { 837 sli4_cmd_init_link_t *init_link = buf; 838 int32_t rc = 0; 839 840 ocs_memset(buf, 0, size); 841 842 init_link->hdr.command = SLI4_MBOX_COMMAND_INIT_LINK; 843 844 /* Most fields only have meaning for FC links */ 845 if (sli4->config.topology != SLI4_READ_CFG_TOPO_FCOE) { 846 init_link->selective_reset_al_pa = reset_alpa; 847 init_link->link_flags.loopback = FALSE; 848 849 init_link->link_speed_selection_code = speed; 850 switch (speed) { 851 case FC_LINK_SPEED_1G: 852 case FC_LINK_SPEED_2G: 853 case FC_LINK_SPEED_4G: 854 case FC_LINK_SPEED_8G: 855 case FC_LINK_SPEED_16G: 856 case FC_LINK_SPEED_32G: 857 init_link->link_flags.fixed_speed = TRUE; 858 break; 859 case FC_LINK_SPEED_10G: 860 ocs_log_test(sli4->os, "unsupported FC speed %d\n", speed); 861 return 0; 862 } 863 864 init_link->link_flags.unfair = FALSE; 865 init_link->link_flags.skip_lirp_lilp = FALSE; 866 init_link->link_flags.gen_loop_validity_check = FALSE; 867 init_link->link_flags.skip_lisa = FALSE; 868 init_link->link_flags.select_hightest_al_pa = FALSE; 869 870 //update topology in the link flags for link bring up 871 ocs_log_info(sli4->os, "bring up link with topology: %d, PTV: %d, TF: %d, PT: %d \n", 872 sli4->config.topology, sli4->config.ptv, sli4->config.tf, sli4->config.pt); 873 if (sli4->config.ptv) 874 rc = sli4_set_link_flags_persistent_topo(sli4, init_link); 875 else 876 rc = sli4_set_link_flags_config_topo(sli4, init_link); 877 878 } 879 880 return rc ? 0 : sizeof(sli4_cmd_init_link_t); 881 } 882 883 /** 884 * @ingroup sli 885 * @brief Write an INIT_VFI command to the provided buffer. 886 * 887 * @param sli4 SLI context pointer. 888 * @param buf Virtual pointer to the destination buffer. 889 * @param size Buffer size, in bytes. 890 * @param vfi VFI 891 * @param fcfi FCFI 892 * @param vpi VPI (Set to -1 if unused.) 893 * 894 * @return Returns the number of bytes written. 895 */ 896 int32_t 897 sli_cmd_init_vfi(sli4_t *sli4, void *buf, size_t size, uint16_t vfi, 898 uint16_t fcfi, uint16_t vpi) 899 { 900 sli4_cmd_init_vfi_t *init_vfi = buf; 901 902 ocs_memset(buf, 0, size); 903 904 init_vfi->hdr.command = SLI4_MBOX_COMMAND_INIT_VFI; 905 906 init_vfi->vfi = vfi; 907 init_vfi->fcfi = fcfi; 908 909 /* 910 * If the VPI is valid, initialize it at the same time as 911 * the VFI 912 */ 913 if (0xffff != vpi) { 914 init_vfi->vp = TRUE; 915 init_vfi->vpi = vpi; 916 } 917 918 return sizeof(sli4_cmd_init_vfi_t); 919 } 920 921 /** 922 * @ingroup sli 923 * @brief Write an INIT_VPI command to the provided buffer. 924 * 925 * @param sli4 SLI context pointer. 926 * @param buf Virtual pointer to the destination buffer. 927 * @param size Buffer size, in bytes. 928 * @param vpi VPI allocated. 929 * @param vfi VFI associated with this VPI. 930 * 931 * @return Returns the number of bytes written. 932 */ 933 int32_t 934 sli_cmd_init_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t vpi, uint16_t vfi) 935 { 936 sli4_cmd_init_vpi_t *init_vpi = buf; 937 938 ocs_memset(buf, 0, size); 939 940 init_vpi->hdr.command = SLI4_MBOX_COMMAND_INIT_VPI; 941 init_vpi->vpi = vpi; 942 init_vpi->vfi = vfi; 943 944 return sizeof(sli4_cmd_init_vpi_t); 945 } 946 947 /** 948 * @ingroup sli 949 * @brief Write a POST_XRI command to the provided buffer. 950 * 951 * @param sli4 SLI context pointer. 952 * @param buf Virtual pointer to the destination buffer. 953 * @param size Buffer size, in bytes. 954 * @param xri_base Starting XRI value for range of XRI given to SLI Port. 955 * @param xri_count Number of XRIs provided to the SLI Port. 956 * 957 * @return Returns the number of bytes written. 958 */ 959 int32_t 960 sli_cmd_post_xri(sli4_t *sli4, void *buf, size_t size, uint16_t xri_base, uint16_t xri_count) 961 { 962 sli4_cmd_post_xri_t *post_xri = buf; 963 964 ocs_memset(buf, 0, size); 965 966 post_xri->hdr.command = SLI4_MBOX_COMMAND_POST_XRI; 967 post_xri->xri_base = xri_base; 968 post_xri->xri_count = xri_count; 969 970 if (sli4->config.auto_xfer_rdy == 0) { 971 post_xri->enx = TRUE; 972 post_xri->val = TRUE; 973 } 974 975 return sizeof(sli4_cmd_post_xri_t); 976 } 977 978 /** 979 * @ingroup sli 980 * @brief Write a RELEASE_XRI command to the provided buffer. 981 * 982 * @param sli4 SLI context pointer. 983 * @param buf Virtual pointer to the destination buffer. 984 * @param size Buffer size, in bytes. 985 * @param num_xri The number of XRIs to be released. 986 * 987 * @return Returns the number of bytes written. 988 */ 989 int32_t 990 sli_cmd_release_xri(sli4_t *sli4, void *buf, size_t size, uint8_t num_xri) 991 { 992 sli4_cmd_release_xri_t *release_xri = buf; 993 994 ocs_memset(buf, 0, size); 995 996 release_xri->hdr.command = SLI4_MBOX_COMMAND_RELEASE_XRI; 997 release_xri->xri_count = num_xri; 998 999 return sizeof(sli4_cmd_release_xri_t); 1000 } 1001 1002 /** 1003 * @brief Write a READ_CONFIG command to the provided buffer. 1004 * 1005 * @param sli4 SLI context pointer. 1006 * @param buf Virtual pointer to the destination buffer. 1007 * @param size Buffer size, in bytes 1008 * 1009 * @return Returns the number of bytes written. 1010 */ 1011 static int32_t 1012 sli_cmd_read_config(sli4_t *sli4, void *buf, size_t size) 1013 { 1014 sli4_cmd_read_config_t *read_config = buf; 1015 1016 ocs_memset(buf, 0, size); 1017 1018 read_config->hdr.command = SLI4_MBOX_COMMAND_READ_CONFIG; 1019 1020 return sizeof(sli4_cmd_read_config_t); 1021 } 1022 1023 /** 1024 * @brief Write a READ_NVPARMS command to the provided buffer. 1025 * 1026 * @param sli4 SLI context pointer. 1027 * @param buf Virtual pointer to the destination buffer. 1028 * @param size Buffer size, in bytes. 1029 * 1030 * @return Returns the number of bytes written. 1031 */ 1032 int32_t 1033 sli_cmd_read_nvparms(sli4_t *sli4, void *buf, size_t size) 1034 { 1035 sli4_cmd_read_nvparms_t *read_nvparms = buf; 1036 1037 ocs_memset(buf, 0, size); 1038 1039 read_nvparms->hdr.command = SLI4_MBOX_COMMAND_READ_NVPARMS; 1040 1041 return sizeof(sli4_cmd_read_nvparms_t); 1042 } 1043 1044 /** 1045 * @brief Write a WRITE_NVPARMS command to the provided buffer. 1046 * 1047 * @param sli4 SLI context pointer. 1048 * @param buf Virtual pointer to the destination buffer. 1049 * @param size Buffer size, in bytes. 1050 * @param wwpn WWPN to write - pointer to array of 8 uint8_t. 1051 * @param wwnn WWNN to write - pointer to array of 8 uint8_t. 1052 * @param hard_alpa Hard ALPA to write. 1053 * @param preferred_d_id Preferred D_ID to write. 1054 * 1055 * @return Returns the number of bytes written. 1056 */ 1057 int32_t 1058 sli_cmd_write_nvparms(sli4_t *sli4, void *buf, size_t size, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa, 1059 uint32_t preferred_d_id) 1060 { 1061 sli4_cmd_write_nvparms_t *write_nvparms = buf; 1062 1063 ocs_memset(buf, 0, size); 1064 1065 write_nvparms->hdr.command = SLI4_MBOX_COMMAND_WRITE_NVPARMS; 1066 ocs_memcpy(write_nvparms->wwpn, wwpn, 8); 1067 ocs_memcpy(write_nvparms->wwnn, wwnn, 8); 1068 write_nvparms->hard_alpa = hard_alpa; 1069 write_nvparms->preferred_d_id = preferred_d_id; 1070 1071 return sizeof(sli4_cmd_write_nvparms_t); 1072 } 1073 1074 /** 1075 * @brief Write a READ_REV command to the provided buffer. 1076 * 1077 * @param sli4 SLI context pointer. 1078 * @param buf Virtual pointer to the destination buffer. 1079 * @param size Buffer size, in bytes. 1080 * @param vpd Pointer to the buffer. 1081 * 1082 * @return Returns the number of bytes written. 1083 */ 1084 static int32_t 1085 sli_cmd_read_rev(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *vpd) 1086 { 1087 sli4_cmd_read_rev_t *read_rev = buf; 1088 1089 ocs_memset(buf, 0, size); 1090 1091 read_rev->hdr.command = SLI4_MBOX_COMMAND_READ_REV; 1092 1093 if (vpd && vpd->size) { 1094 read_rev->vpd = TRUE; 1095 1096 read_rev->available_length = vpd->size; 1097 1098 read_rev->physical_address_low = ocs_addr32_lo(vpd->phys); 1099 read_rev->physical_address_high = ocs_addr32_hi(vpd->phys); 1100 } 1101 1102 return sizeof(sli4_cmd_read_rev_t); 1103 } 1104 1105 /** 1106 * @ingroup sli 1107 * @brief Write a READ_SPARM64 command to the provided buffer. 1108 * 1109 * @param sli4 SLI context pointer. 1110 * @param buf Virtual pointer to the destination buffer. 1111 * @param size Buffer size, in bytes. 1112 * @param dma DMA buffer for the service parameters. 1113 * @param vpi VPI used to determine the WWN. 1114 * 1115 * @return Returns the number of bytes written. 1116 */ 1117 int32_t 1118 sli_cmd_read_sparm64(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, 1119 uint16_t vpi) 1120 { 1121 sli4_cmd_read_sparm64_t *read_sparm64 = buf; 1122 1123 ocs_memset(buf, 0, size); 1124 1125 if (SLI4_READ_SPARM64_VPI_SPECIAL == vpi) { 1126 ocs_log_test(sli4->os, "special VPI not supported!!!\n"); 1127 return -1; 1128 } 1129 1130 if (!dma || !dma->phys) { 1131 ocs_log_test(sli4->os, "bad DMA buffer\n"); 1132 return -1; 1133 } 1134 1135 read_sparm64->hdr.command = SLI4_MBOX_COMMAND_READ_SPARM64; 1136 1137 read_sparm64->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64; 1138 read_sparm64->bde_64.buffer_length = dma->size; 1139 read_sparm64->bde_64.u.data.buffer_address_low = ocs_addr32_lo(dma->phys); 1140 read_sparm64->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys); 1141 1142 read_sparm64->vpi = vpi; 1143 1144 return sizeof(sli4_cmd_read_sparm64_t); 1145 } 1146 1147 /** 1148 * @ingroup sli 1149 * @brief Write a READ_TOPOLOGY command to the provided buffer. 1150 * 1151 * @param sli4 SLI context pointer. 1152 * @param buf Virtual pointer to the destination buffer. 1153 * @param size Buffer size, in bytes. 1154 * @param dma DMA buffer for loop map (optional). 1155 * 1156 * @return Returns the number of bytes written. 1157 */ 1158 int32_t 1159 sli_cmd_read_topology(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma) 1160 { 1161 sli4_cmd_read_topology_t *read_topo = buf; 1162 1163 ocs_memset(buf, 0, size); 1164 1165 read_topo->hdr.command = SLI4_MBOX_COMMAND_READ_TOPOLOGY; 1166 1167 if (dma && dma->size) { 1168 if (dma->size < SLI4_MIN_LOOP_MAP_BYTES) { 1169 ocs_log_test(sli4->os, "loop map buffer too small %jd\n", 1170 dma->size); 1171 return 0; 1172 } 1173 1174 ocs_memset(dma->virt, 0, dma->size); 1175 1176 read_topo->bde_loop_map.bde_type = SLI4_BDE_TYPE_BDE_64; 1177 read_topo->bde_loop_map.buffer_length = dma->size; 1178 read_topo->bde_loop_map.u.data.buffer_address_low = ocs_addr32_lo(dma->phys); 1179 read_topo->bde_loop_map.u.data.buffer_address_high = ocs_addr32_hi(dma->phys); 1180 } 1181 1182 return sizeof(sli4_cmd_read_topology_t); 1183 } 1184 1185 /** 1186 * @ingroup sli 1187 * @brief Write a REG_FCFI command to the provided buffer. 1188 * 1189 * @param sli4 SLI context pointer. 1190 * @param buf Virtual pointer to the destination buffer. 1191 * @param size Buffer size, in bytes. 1192 * @param index FCF index returned by READ_FCF_TABLE. 1193 * @param rq_cfg RQ_ID/R_CTL/TYPE routing information 1194 * @param vlan_id VLAN ID tag. 1195 * 1196 * @return Returns the number of bytes written. 1197 */ 1198 int32_t 1199 sli_cmd_reg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t index, sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG], uint16_t vlan_id) 1200 { 1201 sli4_cmd_reg_fcfi_t *reg_fcfi = buf; 1202 uint32_t i; 1203 1204 ocs_memset(buf, 0, size); 1205 1206 reg_fcfi->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI; 1207 1208 reg_fcfi->fcf_index = index; 1209 1210 for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) { 1211 switch(i) { 1212 case 0: reg_fcfi->rq_id_0 = rq_cfg[0].rq_id; break; 1213 case 1: reg_fcfi->rq_id_1 = rq_cfg[1].rq_id; break; 1214 case 2: reg_fcfi->rq_id_2 = rq_cfg[2].rq_id; break; 1215 case 3: reg_fcfi->rq_id_3 = rq_cfg[3].rq_id; break; 1216 } 1217 reg_fcfi->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask; 1218 reg_fcfi->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match; 1219 reg_fcfi->rq_cfg[i].type_mask = rq_cfg[i].type_mask; 1220 reg_fcfi->rq_cfg[i].type_match = rq_cfg[i].type_match; 1221 } 1222 1223 if (vlan_id) { 1224 reg_fcfi->vv = TRUE; 1225 reg_fcfi->vlan_tag = vlan_id; 1226 } 1227 1228 return sizeof(sli4_cmd_reg_fcfi_t); 1229 } 1230 1231 /** 1232 * @brief Write REG_FCFI_MRQ to provided command buffer 1233 * 1234 * @param sli4 SLI context pointer. 1235 * @param buf Virtual pointer to the destination buffer. 1236 * @param size Buffer size, in bytes. 1237 * @param fcf_index FCF index returned by READ_FCF_TABLE. 1238 * @param vlan_id VLAN ID tag. 1239 * @param rr_quant Round robin quanta if RQ selection policy is 2 1240 * @param rq_selection_policy RQ selection policy 1241 * @param num_rqs Array of count of RQs per filter 1242 * @param rq_ids Array of RQ ids per filter 1243 * @param rq_cfg RQ_ID/R_CTL/TYPE routing information 1244 * 1245 * @return returns 0 for success, a negative error code value for failure. 1246 */ 1247 int32_t 1248 sli_cmd_reg_fcfi_mrq(sli4_t *sli4, void *buf, size_t size, uint8_t mode, 1249 uint16_t fcf_index, uint16_t vlan_id, uint8_t rq_selection_policy, 1250 uint8_t mrq_bit_mask, uint16_t num_mrqs, 1251 sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG]) 1252 { 1253 sli4_cmd_reg_fcfi_mrq_t *reg_fcfi_mrq = buf; 1254 uint32_t i; 1255 1256 ocs_memset(buf, 0, size); 1257 1258 reg_fcfi_mrq->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI_MRQ; 1259 if (mode == SLI4_CMD_REG_FCFI_SET_FCFI_MODE) { 1260 reg_fcfi_mrq->fcf_index = fcf_index; 1261 if (vlan_id) { 1262 reg_fcfi_mrq->vv = TRUE; 1263 reg_fcfi_mrq->vlan_tag = vlan_id; 1264 } 1265 goto done; 1266 } 1267 1268 reg_fcfi_mrq->mode = mode; 1269 for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) { 1270 reg_fcfi_mrq->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask; 1271 reg_fcfi_mrq->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match; 1272 reg_fcfi_mrq->rq_cfg[i].type_mask = rq_cfg[i].type_mask; 1273 reg_fcfi_mrq->rq_cfg[i].type_match = rq_cfg[i].type_match; 1274 1275 switch(i) { 1276 case 3: reg_fcfi_mrq->rq_id_3 = rq_cfg[i].rq_id; break; 1277 case 2: reg_fcfi_mrq->rq_id_2 = rq_cfg[i].rq_id; break; 1278 case 1: reg_fcfi_mrq->rq_id_1 = rq_cfg[i].rq_id; break; 1279 case 0: reg_fcfi_mrq->rq_id_0 = rq_cfg[i].rq_id; break; 1280 } 1281 } 1282 1283 reg_fcfi_mrq->rq_selection_policy = rq_selection_policy; 1284 reg_fcfi_mrq->mrq_filter_bitmask = mrq_bit_mask; 1285 reg_fcfi_mrq->num_mrq_pairs = num_mrqs; 1286 done: 1287 return sizeof(sli4_cmd_reg_fcfi_mrq_t); 1288 } 1289 1290 /** 1291 * @ingroup sli 1292 * @brief Write a REG_RPI command to the provided buffer. 1293 * 1294 * @param sli4 SLI context pointer. 1295 * @param buf Virtual pointer to the destination buffer. 1296 * @param size Buffer size, in bytes. 1297 * @param nport_id Remote F/N_Port_ID. 1298 * @param rpi Previously-allocated Remote Port Indicator. 1299 * @param vpi Previously-allocated Virtual Port Indicator. 1300 * @param dma DMA buffer that contains the remote port's service parameters. 1301 * @param update Boolean indicating an update to an existing RPI (TRUE) 1302 * or a new registration (FALSE). 1303 * 1304 * @return Returns the number of bytes written. 1305 */ 1306 int32_t 1307 sli_cmd_reg_rpi(sli4_t *sli4, void *buf, size_t size, uint32_t nport_id, uint16_t rpi, 1308 uint16_t vpi, ocs_dma_t *dma, uint8_t update, uint8_t enable_t10_pi) 1309 { 1310 sli4_cmd_reg_rpi_t *reg_rpi = buf; 1311 1312 ocs_memset(buf, 0, size); 1313 1314 reg_rpi->hdr.command = SLI4_MBOX_COMMAND_REG_RPI; 1315 1316 reg_rpi->rpi = rpi; 1317 reg_rpi->remote_n_port_id = nport_id; 1318 reg_rpi->upd = update; 1319 reg_rpi->etow = enable_t10_pi; 1320 1321 reg_rpi->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64; 1322 reg_rpi->bde_64.buffer_length = SLI4_REG_RPI_BUF_LEN; 1323 reg_rpi->bde_64.u.data.buffer_address_low = ocs_addr32_lo(dma->phys); 1324 reg_rpi->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys); 1325 1326 reg_rpi->vpi = vpi; 1327 1328 return sizeof(sli4_cmd_reg_rpi_t); 1329 } 1330 1331 /** 1332 * @ingroup sli 1333 * @brief Write a REG_VFI command to the provided buffer. 1334 * 1335 * @param sli4 SLI context pointer. 1336 * @param buf Virtual pointer to the destination buffer. 1337 * @param size Buffer size, in bytes. 1338 * @param domain Pointer to the domain object. 1339 * 1340 * @return Returns the number of bytes written. 1341 */ 1342 int32_t 1343 sli_cmd_reg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain) 1344 { 1345 sli4_cmd_reg_vfi_t *reg_vfi = buf; 1346 1347 if (!sli4 || !buf || !domain) { 1348 return 0; 1349 } 1350 1351 ocs_memset(buf, 0, size); 1352 1353 reg_vfi->hdr.command = SLI4_MBOX_COMMAND_REG_VFI; 1354 1355 reg_vfi->vfi = domain->indicator; 1356 1357 reg_vfi->fcfi = domain->fcf_indicator; 1358 1359 /* TODO contents of domain->dma only valid if topo == FABRIC */ 1360 reg_vfi->sparm.bde_type = SLI4_BDE_TYPE_BDE_64; 1361 reg_vfi->sparm.buffer_length = 0x70; 1362 reg_vfi->sparm.u.data.buffer_address_low = ocs_addr32_lo(domain->dma.phys); 1363 reg_vfi->sparm.u.data.buffer_address_high = ocs_addr32_hi(domain->dma.phys); 1364 1365 reg_vfi->e_d_tov = sli4->config.e_d_tov; 1366 reg_vfi->r_a_tov = sli4->config.r_a_tov; 1367 1368 reg_vfi->vp = TRUE; 1369 reg_vfi->vpi = domain->sport->indicator; 1370 ocs_memcpy(reg_vfi->wwpn, &domain->sport->sli_wwpn, sizeof(reg_vfi->wwpn)); 1371 reg_vfi->local_n_port_id = domain->sport->fc_id; 1372 1373 return sizeof(sli4_cmd_reg_vfi_t); 1374 } 1375 1376 /** 1377 * @ingroup sli 1378 * @brief Write a REG_VPI command to the provided buffer. 1379 * 1380 * @param sli4 SLI context pointer. 1381 * @param buf Virtual pointer to the destination buffer. 1382 * @param size Buffer size, in bytes. 1383 * @param sport Point to SLI Port object. 1384 * @param update Boolean indicating whether to update the existing VPI (true) 1385 * or create a new VPI (false). 1386 * 1387 * @return Returns the number of bytes written. 1388 */ 1389 int32_t 1390 sli_cmd_reg_vpi(sli4_t *sli4, void *buf, size_t size, ocs_sli_port_t *sport, uint8_t update) 1391 { 1392 sli4_cmd_reg_vpi_t *reg_vpi = buf; 1393 1394 if (!sli4 || !buf || !sport) { 1395 return 0; 1396 } 1397 1398 ocs_memset(buf, 0, size); 1399 1400 reg_vpi->hdr.command = SLI4_MBOX_COMMAND_REG_VPI; 1401 1402 reg_vpi->local_n_port_id = sport->fc_id; 1403 reg_vpi->upd = update != 0; 1404 ocs_memcpy(reg_vpi->wwpn, &sport->sli_wwpn, sizeof(reg_vpi->wwpn)); 1405 reg_vpi->vpi = sport->indicator; 1406 reg_vpi->vfi = sport->domain->indicator; 1407 1408 return sizeof(sli4_cmd_reg_vpi_t); 1409 } 1410 1411 /** 1412 * @brief Write a REQUEST_FEATURES command to the provided buffer. 1413 * 1414 * @param sli4 SLI context pointer. 1415 * @param buf Virtual pointer to the destination buffer. 1416 * @param size Buffer size, in bytes. 1417 * @param mask Features to request. 1418 * @param query Use feature query mode (does not change FW). 1419 * 1420 * @return Returns the number of bytes written. 1421 */ 1422 static int32_t 1423 sli_cmd_request_features(sli4_t *sli4, void *buf, size_t size, sli4_features_t mask, uint8_t query) 1424 { 1425 sli4_cmd_request_features_t *features = buf; 1426 1427 ocs_memset(buf, 0, size); 1428 1429 features->hdr.command = SLI4_MBOX_COMMAND_REQUEST_FEATURES; 1430 1431 if (query) { 1432 features->qry = TRUE; 1433 } 1434 features->command.dword = mask.dword; 1435 1436 return sizeof(sli4_cmd_request_features_t); 1437 } 1438 1439 /** 1440 * @ingroup sli 1441 * @brief Write a SLI_CONFIG command to the provided buffer. 1442 * 1443 * @param sli4 SLI context pointer. 1444 * @param buf Virtual pointer to the destination buffer. 1445 * @param size Buffer size, in bytes. 1446 * @param length Length in bytes of attached command. 1447 * @param dma DMA buffer for non-embedded commands. 1448 * 1449 * @return Returns the number of bytes written. 1450 */ 1451 int32_t 1452 sli_cmd_sli_config(sli4_t *sli4, void *buf, size_t size, uint32_t length, ocs_dma_t *dma) 1453 { 1454 sli4_cmd_sli_config_t *sli_config = NULL; 1455 1456 if ((length > sizeof(sli_config->payload.embed)) && (dma == NULL)) { 1457 ocs_log_test(sli4->os, "length(%d) > payload(%ld)\n", 1458 length, sizeof(sli_config->payload.embed)); 1459 return -1; 1460 } 1461 1462 sli_config = buf; 1463 1464 ocs_memset(buf, 0, size); 1465 1466 sli_config->hdr.command = SLI4_MBOX_COMMAND_SLI_CONFIG; 1467 if (NULL == dma) { 1468 sli_config->emb = TRUE; 1469 sli_config->payload_length = length; 1470 } else { 1471 sli_config->emb = FALSE; 1472 1473 sli_config->pmd_count = 1; 1474 1475 sli_config->payload.mem.address_low = ocs_addr32_lo(dma->phys); 1476 sli_config->payload.mem.address_high = ocs_addr32_hi(dma->phys); 1477 sli_config->payload.mem.length = dma->size; 1478 sli_config->payload_length = dma->size; 1479 #if defined(OCS_INCLUDE_DEBUG) 1480 /* save pointer to DMA for BMBX dumping purposes */ 1481 sli4->bmbx_non_emb_pmd = dma; 1482 #endif 1483 } 1484 1485 return offsetof(sli4_cmd_sli_config_t, payload.embed); 1486 } 1487 1488 /** 1489 * @brief Initialize SLI Port control register. 1490 * 1491 * @param sli4 SLI context pointer. 1492 * @param endian Endian value to write. 1493 * 1494 * @return Returns 0 on success, or a negative error code value on failure. 1495 */ 1496 1497 static int32_t 1498 sli_sliport_control(sli4_t *sli4, uint32_t endian) 1499 { 1500 uint32_t iter; 1501 int32_t rc; 1502 1503 rc = -1; 1504 1505 /* Initialize port, endian */ 1506 sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, endian | SLI4_SLIPORT_CONTROL_IP); 1507 1508 for (iter = 0; iter < 3000; iter ++) { 1509 ocs_udelay(SLI4_INIT_PORT_DELAY_US); 1510 if (sli_fw_ready(sli4) == 1) { 1511 rc = 0; 1512 break; 1513 } 1514 } 1515 1516 if (rc != 0) { 1517 ocs_log_crit(sli4->os, "port failed to become ready after initialization\n"); 1518 } 1519 1520 return rc; 1521 } 1522 1523 /** 1524 * @ingroup sli 1525 * @brief Write a UNREG_FCFI command to the provided buffer. 1526 * 1527 * @param sli4 SLI context pointer. 1528 * @param buf Virtual pointer to the destination buffer. 1529 * @param size Buffer size, in bytes. 1530 * @param indicator Indicator value. 1531 * 1532 * @return Returns the number of bytes written. 1533 */ 1534 int32_t 1535 sli_cmd_unreg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator) 1536 { 1537 sli4_cmd_unreg_fcfi_t *unreg_fcfi = buf; 1538 1539 if (!sli4 || !buf) { 1540 return 0; 1541 } 1542 1543 ocs_memset(buf, 0, size); 1544 1545 unreg_fcfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_FCFI; 1546 1547 unreg_fcfi->fcfi = indicator; 1548 1549 return sizeof(sli4_cmd_unreg_fcfi_t); 1550 } 1551 1552 /** 1553 * @ingroup sli 1554 * @brief Write an UNREG_RPI command to the provided buffer. 1555 * 1556 * @param sli4 SLI context pointer. 1557 * @param buf Virtual pointer to the destination buffer. 1558 * @param size Buffer size, in bytes. 1559 * @param indicator Indicator value. 1560 * @param which Type of unregister, such as node, port, domain, or FCF. 1561 * @param fc_id FC address. 1562 * 1563 * @return Returns the number of bytes written. 1564 */ 1565 int32_t 1566 sli_cmd_unreg_rpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, sli4_resource_e which, 1567 uint32_t fc_id) 1568 { 1569 sli4_cmd_unreg_rpi_t *unreg_rpi = buf; 1570 uint8_t index_indicator = 0; 1571 1572 if (!sli4 || !buf) { 1573 return 0; 1574 } 1575 1576 ocs_memset(buf, 0, size); 1577 1578 unreg_rpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_RPI; 1579 1580 switch (which) { 1581 case SLI_RSRC_FCOE_RPI: 1582 index_indicator = SLI4_UNREG_RPI_II_RPI; 1583 if (fc_id != UINT32_MAX) { 1584 unreg_rpi->dp = TRUE; 1585 unreg_rpi->destination_n_port_id = fc_id & 0x00ffffff; 1586 } 1587 break; 1588 case SLI_RSRC_FCOE_VPI: 1589 index_indicator = SLI4_UNREG_RPI_II_VPI; 1590 break; 1591 case SLI_RSRC_FCOE_VFI: 1592 index_indicator = SLI4_UNREG_RPI_II_VFI; 1593 break; 1594 case SLI_RSRC_FCOE_FCFI: 1595 index_indicator = SLI4_UNREG_RPI_II_FCFI; 1596 break; 1597 default: 1598 ocs_log_test(sli4->os, "unknown type %#x\n", which); 1599 return 0; 1600 } 1601 1602 unreg_rpi->ii = index_indicator; 1603 unreg_rpi->index = indicator; 1604 1605 return sizeof(sli4_cmd_unreg_rpi_t); 1606 } 1607 1608 /** 1609 * @ingroup sli 1610 * @brief Write an UNREG_VFI command to the provided buffer. 1611 * 1612 * @param sli4 SLI context pointer. 1613 * @param buf Virtual pointer to the destination buffer. 1614 * @param size Buffer size, in bytes. 1615 * @param domain Pointer to the domain object 1616 * @param which Type of unregister, such as domain, FCFI, or everything. 1617 * 1618 * @return Returns the number of bytes written. 1619 */ 1620 int32_t 1621 sli_cmd_unreg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain, uint32_t which) 1622 { 1623 sli4_cmd_unreg_vfi_t *unreg_vfi = buf; 1624 1625 if (!sli4 || !buf || !domain) { 1626 return 0; 1627 } 1628 1629 ocs_memset(buf, 0, size); 1630 1631 unreg_vfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VFI; 1632 switch (which) { 1633 case SLI4_UNREG_TYPE_DOMAIN: 1634 unreg_vfi->index = domain->indicator; 1635 break; 1636 case SLI4_UNREG_TYPE_FCF: 1637 unreg_vfi->index = domain->fcf_indicator; 1638 break; 1639 case SLI4_UNREG_TYPE_ALL: 1640 unreg_vfi->index = UINT16_MAX; 1641 break; 1642 default: 1643 return 0; 1644 } 1645 1646 if (SLI4_UNREG_TYPE_DOMAIN != which) { 1647 unreg_vfi->ii = SLI4_UNREG_VFI_II_FCFI; 1648 } 1649 1650 return sizeof(sli4_cmd_unreg_vfi_t); 1651 } 1652 1653 /** 1654 * @ingroup sli 1655 * @brief Write an UNREG_VPI command to the provided buffer. 1656 * 1657 * @param sli4 SLI context pointer. 1658 * @param buf Virtual pointer to the destination buffer. 1659 * @param size Buffer size, in bytes. 1660 * @param indicator Indicator value. 1661 * @param which Type of unregister: port, domain, FCFI, everything 1662 * 1663 * @return Returns the number of bytes written. 1664 */ 1665 int32_t 1666 sli_cmd_unreg_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, uint32_t which) 1667 { 1668 sli4_cmd_unreg_vpi_t *unreg_vpi = buf; 1669 1670 if (!sli4 || !buf) { 1671 return 0; 1672 } 1673 1674 ocs_memset(buf, 0, size); 1675 1676 unreg_vpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VPI; 1677 unreg_vpi->index = indicator; 1678 switch (which) { 1679 case SLI4_UNREG_TYPE_PORT: 1680 unreg_vpi->ii = SLI4_UNREG_VPI_II_VPI; 1681 break; 1682 case SLI4_UNREG_TYPE_DOMAIN: 1683 unreg_vpi->ii = SLI4_UNREG_VPI_II_VFI; 1684 break; 1685 case SLI4_UNREG_TYPE_FCF: 1686 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI; 1687 break; 1688 case SLI4_UNREG_TYPE_ALL: 1689 unreg_vpi->index = UINT16_MAX; /* override indicator */ 1690 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI; 1691 break; 1692 default: 1693 return 0; 1694 } 1695 1696 return sizeof(sli4_cmd_unreg_vpi_t); 1697 } 1698 1699 /** 1700 * @ingroup sli 1701 * @brief Write an CONFIG_AUTO_XFER_RDY command to the provided buffer. 1702 * 1703 * @param sli4 SLI context pointer. 1704 * @param buf Virtual pointer to the destination buffer. 1705 * @param size Buffer size, in bytes. 1706 * @param max_burst_len if the write FCP_DL is less than this size, 1707 * then the SLI port will generate the auto XFER_RDY. 1708 * 1709 * @return Returns the number of bytes written. 1710 */ 1711 int32_t 1712 sli_cmd_config_auto_xfer_rdy(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len) 1713 { 1714 sli4_cmd_config_auto_xfer_rdy_t *req = buf; 1715 1716 if (!sli4 || !buf) { 1717 return 0; 1718 } 1719 1720 ocs_memset(buf, 0, size); 1721 1722 req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY; 1723 req->max_burst_len = max_burst_len; 1724 1725 return sizeof(sli4_cmd_config_auto_xfer_rdy_t); 1726 } 1727 1728 /** 1729 * @ingroup sli 1730 * @brief Write an CONFIG_AUTO_XFER_RDY_HP command to the provided buffer. 1731 * 1732 * @param sli4 SLI context pointer. 1733 * @param buf Virtual pointer to the destination buffer. 1734 * @param size Buffer size, in bytes. 1735 * @param max_burst_len if the write FCP_DL is less than this size, 1736 * @param esoc enable start offset computation, 1737 * @param block_size block size, 1738 * then the SLI port will generate the auto XFER_RDY. 1739 * 1740 * @return Returns the number of bytes written. 1741 */ 1742 int32_t 1743 sli_cmd_config_auto_xfer_rdy_hp(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len, 1744 uint32_t esoc, uint32_t block_size ) 1745 { 1746 sli4_cmd_config_auto_xfer_rdy_hp_t *req = buf; 1747 1748 if (!sli4 || !buf) { 1749 return 0; 1750 } 1751 1752 ocs_memset(buf, 0, size); 1753 1754 req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY_HP; 1755 req->max_burst_len = max_burst_len; 1756 req->esoc = esoc; 1757 req->block_size = block_size; 1758 return sizeof(sli4_cmd_config_auto_xfer_rdy_hp_t); 1759 } 1760 1761 /** 1762 * @brief Write a COMMON_FUNCTION_RESET command. 1763 * 1764 * @param sli4 SLI context. 1765 * @param buf Destination buffer for the command. 1766 * @param size Buffer size, in bytes. 1767 * 1768 * @return Returns the number of bytes written. 1769 */ 1770 static int32_t 1771 sli_cmd_common_function_reset(sli4_t *sli4, void *buf, size_t size) 1772 { 1773 sli4_req_common_function_reset_t *reset = NULL; 1774 uint32_t sli_config_off = 0; 1775 1776 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 1777 uint32_t payload_size; 1778 1779 /* Payload length must accommodate both request and response */ 1780 payload_size = max(sizeof(sli4_req_common_function_reset_t), 1781 sizeof(sli4_res_common_function_reset_t)); 1782 1783 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 1784 NULL); 1785 } 1786 reset = (sli4_req_common_function_reset_t *)((uint8_t *)buf + sli_config_off); 1787 1788 reset->hdr.opcode = SLI4_OPC_COMMON_FUNCTION_RESET; 1789 reset->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 1790 1791 return(sli_config_off + sizeof(sli4_req_common_function_reset_t)); 1792 } 1793 1794 /** 1795 * @brief Write a COMMON_CREATE_CQ command. 1796 * 1797 * @param sli4 SLI context. 1798 * @param buf Destination buffer for the command. 1799 * @param size Buffer size, in bytes. 1800 * @param qmem DMA memory for the queue. 1801 * @param eq_id Associated EQ_ID 1802 * @param ignored This parameter carries the ULP which is only used for WQ and RQs 1803 * 1804 * @note This creates a Version 0 message. 1805 * 1806 * @return Returns the number of bytes written. 1807 */ 1808 static int32_t 1809 sli_cmd_common_create_cq(sli4_t *sli4, void *buf, size_t size, 1810 ocs_dma_t *qmem, uint16_t eq_id, uint16_t ignored) 1811 { 1812 sli4_req_common_create_cq_v0_t *cqv0 = NULL; 1813 sli4_req_common_create_cq_v2_t *cqv2 = NULL; 1814 uint32_t sli_config_off = 0; 1815 uint32_t p; 1816 uintptr_t addr; 1817 uint32_t if_type = sli4->if_type; 1818 uint32_t page_bytes = 0; 1819 uint32_t num_pages = 0; 1820 uint32_t cmd_size = 0; 1821 uint32_t page_size = 0; 1822 uint32_t n_cqe = 0; 1823 1824 /* First calculate number of pages and the mailbox cmd length */ 1825 switch (if_type) 1826 { 1827 case SLI4_IF_TYPE_BE3_SKH_PF: 1828 page_bytes = SLI_PAGE_SIZE; 1829 num_pages = sli_page_count(qmem->size, page_bytes); 1830 cmd_size = sizeof(sli4_req_common_create_cq_v0_t) + (8 * num_pages); 1831 break; 1832 case SLI4_IF_TYPE_LANCER_FC_ETH: 1833 case SLI4_IF_TYPE_LANCER_G7: 1834 n_cqe = qmem->size / SLI4_CQE_BYTES; 1835 switch (n_cqe) { 1836 case 256: 1837 case 512: 1838 case 1024: 1839 case 2048: 1840 page_size = 1; 1841 break; 1842 case 4096: 1843 page_size = 2; 1844 break; 1845 default: 1846 return 0; 1847 } 1848 page_bytes = page_size * SLI_PAGE_SIZE; 1849 num_pages = sli_page_count(qmem->size, page_bytes); 1850 cmd_size = sizeof(sli4_req_common_create_cq_v2_t) + (8 * num_pages); 1851 break; 1852 default: 1853 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", if_type); 1854 return -1; 1855 } 1856 1857 /* now that we have the mailbox command size, we can set SLI_CONFIG fields */ 1858 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 1859 uint32_t payload_size; 1860 1861 /* Payload length must accommodate both request and response */ 1862 payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_t)); 1863 1864 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 1865 NULL); 1866 } 1867 1868 switch (if_type) 1869 { 1870 case SLI4_IF_TYPE_BE3_SKH_PF: 1871 cqv0 = (sli4_req_common_create_cq_v0_t *)((uint8_t *)buf + sli_config_off); 1872 cqv0->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ; 1873 cqv0->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 1874 cqv0->hdr.version = 0; 1875 cqv0->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t); 1876 1877 /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */ 1878 cqv0->num_pages = num_pages; 1879 switch (cqv0->num_pages) { 1880 case 1: 1881 cqv0->cqecnt = SLI4_CQ_CNT_256; 1882 break; 1883 case 2: 1884 cqv0->cqecnt = SLI4_CQ_CNT_512; 1885 break; 1886 case 4: 1887 cqv0->cqecnt = SLI4_CQ_CNT_1024; 1888 break; 1889 default: 1890 ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv0->num_pages); 1891 return -1; 1892 } 1893 cqv0->evt = TRUE; 1894 cqv0->valid = TRUE; 1895 /* TODO cq->nodelay = ???; */ 1896 /* TODO cq->clswm = ???; */ 1897 cqv0->arm = FALSE; 1898 cqv0->eq_id = eq_id; 1899 1900 for (p = 0, addr = qmem->phys; 1901 p < cqv0->num_pages; 1902 p++, addr += page_bytes) { 1903 cqv0->page_physical_address[p].low = ocs_addr32_lo(addr); 1904 cqv0->page_physical_address[p].high = ocs_addr32_hi(addr); 1905 } 1906 1907 break; 1908 case SLI4_IF_TYPE_LANCER_FC_ETH: 1909 case SLI4_IF_TYPE_LANCER_G7: 1910 { 1911 cqv2 = (sli4_req_common_create_cq_v2_t *)((uint8_t *)buf + sli_config_off); 1912 cqv2->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ; 1913 cqv2->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 1914 cqv2->hdr.version = 2; 1915 cqv2->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t); 1916 1917 if (if_type == SLI4_IF_TYPE_LANCER_G7) 1918 cqv2->autovalid = TRUE; 1919 1920 cqv2->page_size = page_size; 1921 1922 /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.3) */ 1923 cqv2->num_pages = num_pages; 1924 if (!cqv2->num_pages || (cqv2->num_pages > SLI4_COMMON_CREATE_CQ_V2_MAX_PAGES)) { 1925 return 0; 1926 } 1927 1928 switch (cqv2->num_pages) { 1929 case 1: 1930 cqv2->cqecnt = SLI4_CQ_CNT_256; 1931 break; 1932 case 2: 1933 cqv2->cqecnt = SLI4_CQ_CNT_512; 1934 break; 1935 case 4: 1936 cqv2->cqecnt = SLI4_CQ_CNT_1024; 1937 break; 1938 case 8: 1939 cqv2->cqecnt = SLI4_CQ_CNT_LARGE; 1940 cqv2->cqe_count = n_cqe; 1941 break; 1942 default: 1943 ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv2->num_pages); 1944 return -1; 1945 } 1946 1947 cqv2->evt = TRUE; 1948 cqv2->valid = TRUE; 1949 /* TODO cq->nodelay = ???; */ 1950 /* TODO cq->clswm = ???; */ 1951 cqv2->arm = FALSE; 1952 cqv2->eq_id = eq_id; 1953 1954 for (p = 0, addr = qmem->phys; 1955 p < cqv2->num_pages; 1956 p++, addr += page_bytes) { 1957 cqv2->page_physical_address[p].low = ocs_addr32_lo(addr); 1958 cqv2->page_physical_address[p].high = ocs_addr32_hi(addr); 1959 } 1960 } 1961 break; 1962 } 1963 1964 return (sli_config_off + cmd_size); 1965 } 1966 1967 /** 1968 * @brief Write a COMMON_DESTROY_CQ command. 1969 * 1970 * @param sli4 SLI context. 1971 * @param buf Destination buffer for the command. 1972 * @param size Buffer size, in bytes. 1973 * @param cq_id CQ ID 1974 * 1975 * @note This creates a Version 0 message. 1976 * 1977 * @return Returns the number of bytes written. 1978 */ 1979 static int32_t 1980 sli_cmd_common_destroy_cq(sli4_t *sli4, void *buf, size_t size, uint16_t cq_id) 1981 { 1982 sli4_req_common_destroy_cq_t *cq = NULL; 1983 uint32_t sli_config_off = 0; 1984 1985 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 1986 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 1987 /* Payload length must accommodate both request and response */ 1988 max(sizeof(sli4_req_common_destroy_cq_t), 1989 sizeof(sli4_res_hdr_t)), 1990 NULL); 1991 } 1992 cq = (sli4_req_common_destroy_cq_t *)((uint8_t *)buf + sli_config_off); 1993 1994 cq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_CQ; 1995 cq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 1996 cq->hdr.request_length = sizeof(sli4_req_common_destroy_cq_t) - 1997 sizeof(sli4_req_hdr_t); 1998 cq->cq_id = cq_id; 1999 2000 return(sli_config_off + sizeof(sli4_req_common_destroy_cq_t)); 2001 } 2002 2003 /** 2004 * @brief Write a COMMON_MODIFY_EQ_DELAY command. 2005 * 2006 * @param sli4 SLI context. 2007 * @param buf Destination buffer for the command. 2008 * @param size Buffer size, in bytes. 2009 * @param q Queue object array. 2010 * @param num_q Queue object array count. 2011 * @param shift Phase shift for staggering interrupts. 2012 * @param delay_mult Delay multiplier for limiting interrupt frequency. 2013 * 2014 * @return Returns the number of bytes written. 2015 */ 2016 static int32_t 2017 sli_cmd_common_modify_eq_delay(sli4_t *sli4, void *buf, size_t size, sli4_queue_t *q, int num_q, uint32_t shift, 2018 uint32_t delay_mult) 2019 { 2020 sli4_req_common_modify_eq_delay_t *modify_delay = NULL; 2021 uint32_t sli_config_off = 0; 2022 int i; 2023 2024 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2025 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2026 /* Payload length must accommodate both request and response */ 2027 max(sizeof(sli4_req_common_modify_eq_delay_t), sizeof(sli4_res_hdr_t)), 2028 NULL); 2029 } 2030 2031 modify_delay = (sli4_req_common_modify_eq_delay_t *)((uint8_t *)buf + sli_config_off); 2032 2033 modify_delay->hdr.opcode = SLI4_OPC_COMMON_MODIFY_EQ_DELAY; 2034 modify_delay->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2035 modify_delay->hdr.request_length = sizeof(sli4_req_common_modify_eq_delay_t) - 2036 sizeof(sli4_req_hdr_t); 2037 2038 modify_delay->num_eq = num_q; 2039 2040 for (i = 0; i<num_q; i++) { 2041 modify_delay->eq_delay_record[i].eq_id = q[i].id; 2042 modify_delay->eq_delay_record[i].phase = shift; 2043 modify_delay->eq_delay_record[i].delay_multiplier = delay_mult; 2044 } 2045 2046 return(sli_config_off + sizeof(sli4_req_common_modify_eq_delay_t)); 2047 } 2048 2049 /** 2050 * @brief Write a COMMON_CREATE_EQ command. 2051 * 2052 * @param sli4 SLI context. 2053 * @param buf Destination buffer for the command. 2054 * @param size Buffer size, in bytes. 2055 * @param qmem DMA memory for the queue. 2056 * @param ignored1 Ignored (used for consistency among queue creation functions). 2057 * @param ignored2 Ignored (used for consistency among queue creation functions). 2058 * 2059 * @note Other queue creation routines use the last parameter to pass in 2060 * the associated Q_ID and ULP. EQ doesn't have an associated queue or ULP, 2061 * so these parameters are ignored 2062 * 2063 * @note This creates a Version 0 message 2064 * 2065 * @return Returns the number of bytes written. 2066 */ 2067 static int32_t 2068 sli_cmd_common_create_eq(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem, 2069 uint16_t ignored1, uint16_t ignored2) 2070 { 2071 sli4_req_common_create_eq_t *eq = NULL; 2072 uint32_t sli_config_off = 0; 2073 uint32_t p; 2074 uintptr_t addr; 2075 2076 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2077 uint32_t payload_size; 2078 2079 /* Payload length must accommodate both request and response */ 2080 payload_size = max(sizeof(sli4_req_common_create_eq_t), 2081 sizeof(sli4_res_common_create_queue_t)); 2082 2083 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 2084 NULL); 2085 } 2086 eq = (sli4_req_common_create_eq_t *)((uint8_t *)buf + sli_config_off); 2087 2088 eq->hdr.opcode = SLI4_OPC_COMMON_CREATE_EQ; 2089 eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2090 eq->hdr.request_length = sizeof(sli4_req_common_create_eq_t) - 2091 sizeof(sli4_req_hdr_t); 2092 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) { 2093 eq->hdr.version = 2; 2094 eq->autovalid = TRUE; 2095 } 2096 /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */ 2097 eq->num_pages = qmem->size / SLI_PAGE_SIZE; 2098 switch (eq->num_pages) { 2099 case 1: 2100 eq->eqesz = SLI4_EQE_SIZE_4; 2101 eq->count = SLI4_EQ_CNT_1024; 2102 break; 2103 case 2: 2104 eq->eqesz = SLI4_EQE_SIZE_4; 2105 eq->count = SLI4_EQ_CNT_2048; 2106 break; 2107 case 4: 2108 eq->eqesz = SLI4_EQE_SIZE_4; 2109 eq->count = SLI4_EQ_CNT_4096; 2110 break; 2111 default: 2112 ocs_log_test(sli4->os, "num_pages %d not valid\n", eq->num_pages); 2113 return -1; 2114 } 2115 eq->valid = TRUE; 2116 eq->arm = FALSE; 2117 eq->delay_multiplier = 32; 2118 2119 for (p = 0, addr = qmem->phys; 2120 p < eq->num_pages; 2121 p++, addr += SLI_PAGE_SIZE) { 2122 eq->page_address[p].low = ocs_addr32_lo(addr); 2123 eq->page_address[p].high = ocs_addr32_hi(addr); 2124 } 2125 2126 return(sli_config_off + sizeof(sli4_req_common_create_eq_t)); 2127 } 2128 2129 /** 2130 * @brief Write a COMMON_DESTROY_EQ command. 2131 * 2132 * @param sli4 SLI context. 2133 * @param buf Destination buffer for the command. 2134 * @param size Buffer size, in bytes. 2135 * @param eq_id Queue ID to destroy. 2136 * 2137 * @note Other queue creation routines use the last parameter to pass in 2138 * the associated Q_ID. EQ doesn't have an associated queue so this 2139 * parameter is ignored. 2140 * 2141 * @note This creates a Version 0 message. 2142 * 2143 * @return Returns the number of bytes written. 2144 */ 2145 static int32_t 2146 sli_cmd_common_destroy_eq(sli4_t *sli4, void *buf, size_t size, uint16_t eq_id) 2147 { 2148 sli4_req_common_destroy_eq_t *eq = NULL; 2149 uint32_t sli_config_off = 0; 2150 2151 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2152 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2153 /* Payload length must accommodate both request and response */ 2154 max(sizeof(sli4_req_common_destroy_eq_t), 2155 sizeof(sli4_res_hdr_t)), 2156 NULL); 2157 } 2158 eq = (sli4_req_common_destroy_eq_t *)((uint8_t *)buf + sli_config_off); 2159 2160 eq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_EQ; 2161 eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2162 eq->hdr.request_length = sizeof(sli4_req_common_destroy_eq_t) - 2163 sizeof(sli4_req_hdr_t); 2164 2165 eq->eq_id = eq_id; 2166 2167 return(sli_config_off + sizeof(sli4_req_common_destroy_eq_t)); 2168 } 2169 2170 /** 2171 * @brief Write a LOWLEVEL_SET_WATCHDOG command. 2172 * 2173 * @param sli4 SLI context. 2174 * @param buf Destination buffer for the command. 2175 * @param size Buffer size, in bytes. 2176 * @param timeout watchdog timer timeout in seconds 2177 * 2178 * @return void 2179 */ 2180 void 2181 sli4_cmd_lowlevel_set_watchdog(sli4_t *sli4, void *buf, size_t size, uint16_t timeout) 2182 { 2183 2184 sli4_req_lowlevel_set_watchdog_t *req = NULL; 2185 uint32_t sli_config_off = 0; 2186 2187 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2188 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2189 /* Payload length must accommodate both request and response */ 2190 max(sizeof(sli4_req_lowlevel_set_watchdog_t), 2191 sizeof(sli4_res_lowlevel_set_watchdog_t)), 2192 NULL); 2193 } 2194 req = (sli4_req_lowlevel_set_watchdog_t *)((uint8_t *)buf + sli_config_off); 2195 2196 req->hdr.opcode = SLI4_OPC_LOWLEVEL_SET_WATCHDOG; 2197 req->hdr.subsystem = SLI4_SUBSYSTEM_LOWLEVEL; 2198 req->hdr.request_length = sizeof(sli4_req_lowlevel_set_watchdog_t) - sizeof(sli4_req_hdr_t); 2199 req->watchdog_timeout = timeout; 2200 2201 return; 2202 } 2203 2204 static int32_t 2205 sli_cmd_common_get_cntl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma) 2206 { 2207 sli4_req_hdr_t *hdr = NULL; 2208 uint32_t sli_config_off = 0; 2209 2210 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2211 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2212 sizeof(sli4_req_hdr_t), 2213 dma); 2214 } 2215 2216 if (dma == NULL) { 2217 return 0; 2218 } 2219 2220 ocs_memset(dma->virt, 0, dma->size); 2221 2222 hdr = dma->virt; 2223 2224 hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ATTRIBUTES; 2225 hdr->subsystem = SLI4_SUBSYSTEM_COMMON; 2226 hdr->request_length = dma->size; 2227 2228 return(sli_config_off + sizeof(sli4_req_hdr_t)); 2229 } 2230 2231 /** 2232 * @brief Write a COMMON_GET_CNTL_ADDL_ATTRIBUTES command. 2233 * 2234 * @param sli4 SLI context. 2235 * @param buf Destination buffer for the command. 2236 * @param size Buffer size, in bytes. 2237 * @param dma DMA structure from which the data will be copied. 2238 * 2239 * @note This creates a Version 0 message. 2240 * 2241 * @return Returns the number of bytes written. 2242 */ 2243 static int32_t 2244 sli_cmd_common_get_cntl_addl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma) 2245 { 2246 sli4_req_hdr_t *hdr = NULL; 2247 uint32_t sli_config_off = 0; 2248 2249 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2250 sli_config_off = sli_cmd_sli_config(sli4, buf, size, sizeof(sli4_req_hdr_t), dma); 2251 } 2252 2253 if (dma == NULL) { 2254 return 0; 2255 } 2256 2257 ocs_memset(dma->virt, 0, dma->size); 2258 2259 hdr = dma->virt; 2260 2261 hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ADDL_ATTRIBUTES; 2262 hdr->subsystem = SLI4_SUBSYSTEM_COMMON; 2263 hdr->request_length = dma->size; 2264 2265 return(sli_config_off + sizeof(sli4_req_hdr_t)); 2266 } 2267 2268 /** 2269 * @brief Write a COMMON_CREATE_MQ_EXT command. 2270 * 2271 * @param sli4 SLI context. 2272 * @param buf Destination buffer for the command. 2273 * @param size Buffer size, in bytes. 2274 * @param qmem DMA memory for the queue. 2275 * @param cq_id Associated CQ_ID. 2276 * @param ignored This parameter carries the ULP which is only used for WQ and RQs 2277 * 2278 * @note This creates a Version 0 message. 2279 * 2280 * @return Returns the number of bytes written. 2281 */ 2282 static int32_t 2283 sli_cmd_common_create_mq_ext(sli4_t *sli4, void *buf, size_t size, 2284 ocs_dma_t *qmem, uint16_t cq_id, uint16_t ignored) 2285 { 2286 sli4_req_common_create_mq_ext_t *mq = NULL; 2287 uint32_t sli_config_off = 0; 2288 uint32_t p; 2289 uintptr_t addr; 2290 2291 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2292 uint32_t payload_size; 2293 2294 /* Payload length must accommodate both request and response */ 2295 payload_size = max(sizeof(sli4_req_common_create_mq_ext_t), 2296 sizeof(sli4_res_common_create_queue_t)); 2297 2298 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 2299 NULL); 2300 } 2301 mq = (sli4_req_common_create_mq_ext_t *)((uint8_t *)buf + sli_config_off); 2302 2303 mq->hdr.opcode = SLI4_OPC_COMMON_CREATE_MQ_EXT; 2304 mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2305 mq->hdr.request_length = sizeof(sli4_req_common_create_mq_ext_t) - 2306 sizeof(sli4_req_hdr_t); 2307 /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.12) */ 2308 mq->num_pages = qmem->size / SLI_PAGE_SIZE; 2309 switch (mq->num_pages) { 2310 case 1: 2311 mq->ring_size = SLI4_MQE_SIZE_16; 2312 break; 2313 case 2: 2314 mq->ring_size = SLI4_MQE_SIZE_32; 2315 break; 2316 case 4: 2317 mq->ring_size = SLI4_MQE_SIZE_64; 2318 break; 2319 case 8: 2320 mq->ring_size = SLI4_MQE_SIZE_128; 2321 break; 2322 default: 2323 ocs_log_test(sli4->os, "num_pages %d not valid\n", mq->num_pages); 2324 return -1; 2325 } 2326 2327 /* TODO break this down by sli4->config.topology */ 2328 mq->async_event_bitmap = SLI4_ASYNC_EVT_FC_FCOE; 2329 2330 if (sli4->config.mq_create_version) { 2331 mq->cq_id_v1 = cq_id; 2332 mq->hdr.version = 1; 2333 } 2334 else { 2335 mq->cq_id_v0 = cq_id; 2336 } 2337 mq->val = TRUE; 2338 2339 for (p = 0, addr = qmem->phys; 2340 p < mq->num_pages; 2341 p++, addr += SLI_PAGE_SIZE) { 2342 mq->page_physical_address[p].low = ocs_addr32_lo(addr); 2343 mq->page_physical_address[p].high = ocs_addr32_hi(addr); 2344 } 2345 2346 return(sli_config_off + sizeof(sli4_req_common_create_mq_ext_t)); 2347 } 2348 2349 /** 2350 * @brief Write a COMMON_DESTROY_MQ command. 2351 * 2352 * @param sli4 SLI context. 2353 * @param buf Destination buffer for the command. 2354 * @param size Buffer size, in bytes. 2355 * @param mq_id MQ ID 2356 * 2357 * @note This creates a Version 0 message. 2358 * 2359 * @return Returns the number of bytes written. 2360 */ 2361 static int32_t 2362 sli_cmd_common_destroy_mq(sli4_t *sli4, void *buf, size_t size, uint16_t mq_id) 2363 { 2364 sli4_req_common_destroy_mq_t *mq = NULL; 2365 uint32_t sli_config_off = 0; 2366 2367 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2368 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2369 /* Payload length must accommodate both request and response */ 2370 max(sizeof(sli4_req_common_destroy_mq_t), 2371 sizeof(sli4_res_hdr_t)), 2372 NULL); 2373 } 2374 mq = (sli4_req_common_destroy_mq_t *)((uint8_t *)buf + sli_config_off); 2375 2376 mq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_MQ; 2377 mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2378 mq->hdr.request_length = sizeof(sli4_req_common_destroy_mq_t) - 2379 sizeof(sli4_req_hdr_t); 2380 2381 mq->mq_id = mq_id; 2382 2383 return(sli_config_off + sizeof(sli4_req_common_destroy_mq_t)); 2384 } 2385 2386 /** 2387 * @ingroup sli 2388 * @brief Write a COMMON_NOP command 2389 * 2390 * @param sli4 SLI context. 2391 * @param buf Destination buffer for the command. 2392 * @param size Buffer size, in bytes. 2393 * @param context NOP context value (passed to response, except on FC/FCoE). 2394 * 2395 * @return Returns the number of bytes written. 2396 */ 2397 int32_t 2398 sli_cmd_common_nop(sli4_t *sli4, void *buf, size_t size, uint64_t context) 2399 { 2400 sli4_req_common_nop_t *nop = NULL; 2401 uint32_t sli_config_off = 0; 2402 2403 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2404 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2405 /* Payload length must accommodate both request and response */ 2406 max(sizeof(sli4_req_common_nop_t), sizeof(sli4_res_common_nop_t)), 2407 NULL); 2408 } 2409 2410 nop = (sli4_req_common_nop_t *)((uint8_t *)buf + sli_config_off); 2411 2412 nop->hdr.opcode = SLI4_OPC_COMMON_NOP; 2413 nop->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2414 nop->hdr.request_length = 8; 2415 2416 ocs_memcpy(&nop->context, &context, sizeof(context)); 2417 2418 return(sli_config_off + sizeof(sli4_req_common_nop_t)); 2419 } 2420 2421 /** 2422 * @ingroup sli 2423 * @brief Write a COMMON_GET_RESOURCE_EXTENT_INFO command. 2424 * 2425 * @param sli4 SLI context. 2426 * @param buf Destination buffer for the command. 2427 * @param size Buffer size, in bytes. 2428 * @param rtype Resource type (for example, XRI, VFI, VPI, and RPI). 2429 * 2430 * @return Returns the number of bytes written. 2431 */ 2432 int32_t 2433 sli_cmd_common_get_resource_extent_info(sli4_t *sli4, void *buf, size_t size, uint16_t rtype) 2434 { 2435 sli4_req_common_get_resource_extent_info_t *extent = NULL; 2436 uint32_t sli_config_off = 0; 2437 2438 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2439 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2440 sizeof(sli4_req_common_get_resource_extent_info_t), 2441 NULL); 2442 } 2443 2444 extent = (sli4_req_common_get_resource_extent_info_t *)((uint8_t *)buf + sli_config_off); 2445 2446 extent->hdr.opcode = SLI4_OPC_COMMON_GET_RESOURCE_EXTENT_INFO; 2447 extent->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2448 extent->hdr.request_length = 4; 2449 2450 extent->resource_type = rtype; 2451 2452 return(sli_config_off + sizeof(sli4_req_common_get_resource_extent_info_t)); 2453 } 2454 2455 /** 2456 * @ingroup sli 2457 * @brief Write a COMMON_GET_SLI4_PARAMETERS command. 2458 * 2459 * @param sli4 SLI context. 2460 * @param buf Destination buffer for the command. 2461 * @param size Buffer size, in bytes. 2462 * 2463 * @return Returns the number of bytes written. 2464 */ 2465 int32_t 2466 sli_cmd_common_get_sli4_parameters(sli4_t *sli4, void *buf, size_t size) 2467 { 2468 sli4_req_hdr_t *hdr = NULL; 2469 uint32_t sli_config_off = 0; 2470 2471 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2472 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2473 sizeof(sli4_res_common_get_sli4_parameters_t), 2474 NULL); 2475 } 2476 2477 hdr = (sli4_req_hdr_t *)((uint8_t *)buf + sli_config_off); 2478 2479 hdr->opcode = SLI4_OPC_COMMON_GET_SLI4_PARAMETERS; 2480 hdr->subsystem = SLI4_SUBSYSTEM_COMMON; 2481 hdr->request_length = 0x50; 2482 2483 return(sli_config_off + sizeof(sli4_req_hdr_t)); 2484 } 2485 2486 /** 2487 * @brief Write a COMMON_QUERY_FW_CONFIG command to the provided buffer. 2488 * 2489 * @param sli4 SLI context pointer. 2490 * @param buf Virtual pointer to destination buffer. 2491 * @param size Buffer size in bytes. 2492 * 2493 * @return Returns the number of bytes written 2494 */ 2495 static int32_t 2496 sli_cmd_common_query_fw_config(sli4_t *sli4, void *buf, size_t size) 2497 { 2498 sli4_req_common_query_fw_config_t *fw_config; 2499 uint32_t sli_config_off = 0; 2500 uint32_t payload_size; 2501 2502 /* Payload length must accommodate both request and response */ 2503 payload_size = max(sizeof(sli4_req_common_query_fw_config_t), 2504 sizeof(sli4_res_common_query_fw_config_t)); 2505 2506 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2507 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2508 payload_size, 2509 NULL); 2510 } 2511 2512 fw_config = (sli4_req_common_query_fw_config_t*)((uint8_t*)buf + sli_config_off); 2513 fw_config->hdr.opcode = SLI4_OPC_COMMON_QUERY_FW_CONFIG; 2514 fw_config->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2515 fw_config->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 2516 return sli_config_off + sizeof(sli4_req_common_query_fw_config_t); 2517 } 2518 2519 /** 2520 * @brief Write a COMMON_GET_PORT_NAME command to the provided buffer. 2521 * 2522 * @param sli4 SLI context pointer. 2523 * @param buf Virtual pointer to destination buffer. 2524 * @param size Buffer size in bytes. 2525 * 2526 * @note Function supports both version 0 and 1 forms of this command via 2527 * the IF_TYPE. 2528 * 2529 * @return Returns the number of bytes written. 2530 */ 2531 static int32_t 2532 sli_cmd_common_get_port_name(sli4_t *sli4, void *buf, size_t size) 2533 { 2534 sli4_req_common_get_port_name_t *port_name; 2535 uint32_t sli_config_off = 0; 2536 uint32_t payload_size; 2537 uint8_t version = 0; 2538 uint8_t pt = 0; 2539 2540 /* Select command version according to IF_TYPE */ 2541 switch (sli4->if_type) { 2542 case SLI4_IF_TYPE_BE3_SKH_PF: 2543 case SLI4_IF_TYPE_BE3_SKH_VF: 2544 version = 0; 2545 break; 2546 case SLI4_IF_TYPE_LANCER_FC_ETH: 2547 case SLI4_IF_TYPE_LANCER_RDMA: 2548 case SLI4_IF_TYPE_LANCER_G7: 2549 version = 1; 2550 break; 2551 default: 2552 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", sli4->if_type); 2553 return 0; 2554 } 2555 2556 /* Payload length must accommodate both request and response */ 2557 payload_size = max(sizeof(sli4_req_common_get_port_name_t), 2558 sizeof(sli4_res_common_get_port_name_t)); 2559 2560 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2561 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2562 payload_size, 2563 NULL); 2564 2565 pt = 1; 2566 } 2567 2568 port_name = (sli4_req_common_get_port_name_t *)((uint8_t *)buf + sli_config_off); 2569 2570 port_name->hdr.opcode = SLI4_OPC_COMMON_GET_PORT_NAME; 2571 port_name->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2572 port_name->hdr.request_length = sizeof(sli4_req_hdr_t) + (version * sizeof(uint32_t)); 2573 port_name->hdr.version = version; 2574 2575 /* Set the port type value (ethernet=0, FC=1) for V1 commands */ 2576 if (version == 1) { 2577 port_name->pt = pt; 2578 } 2579 2580 return sli_config_off + port_name->hdr.request_length; 2581 } 2582 2583 /** 2584 * @ingroup sli 2585 * @brief Write a COMMON_WRITE_OBJECT command. 2586 * 2587 * @param sli4 SLI context. 2588 * @param buf Destination buffer for the command. 2589 * @param size Buffer size, in bytes. 2590 * @param noc True if the object should be written but not committed to flash. 2591 * @param eof True if this is the last write for this object. 2592 * @param desired_write_length Number of bytes of data to write to the object. 2593 * @param offset Offset, in bytes, from the start of the object. 2594 * @param object_name Name of the object to write. 2595 * @param dma DMA structure from which the data will be copied. 2596 * 2597 * @return Returns the number of bytes written. 2598 */ 2599 int32_t 2600 sli_cmd_common_write_object(sli4_t *sli4, void *buf, size_t size, 2601 uint16_t noc, uint16_t eof, uint32_t desired_write_length, 2602 uint32_t offset, 2603 char *object_name, 2604 ocs_dma_t *dma) 2605 { 2606 sli4_req_common_write_object_t *wr_obj = NULL; 2607 uint32_t sli_config_off = 0; 2608 sli4_bde_t *host_buffer; 2609 2610 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2611 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2612 sizeof (sli4_req_common_write_object_t) + sizeof (sli4_bde_t), 2613 NULL); 2614 } 2615 2616 wr_obj = (sli4_req_common_write_object_t *)((uint8_t *)buf + sli_config_off); 2617 2618 wr_obj->hdr.opcode = SLI4_OPC_COMMON_WRITE_OBJECT; 2619 wr_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2620 wr_obj->hdr.request_length = sizeof(*wr_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t); 2621 wr_obj->hdr.timeout = 0; 2622 wr_obj->hdr.version = 0; 2623 2624 wr_obj->noc = noc; 2625 wr_obj->eof = eof; 2626 wr_obj->desired_write_length = desired_write_length; 2627 wr_obj->write_offset = offset; 2628 ocs_strncpy(wr_obj->object_name, object_name, sizeof(wr_obj->object_name)); 2629 wr_obj->host_buffer_descriptor_count = 1; 2630 2631 host_buffer = (sli4_bde_t *)wr_obj->host_buffer_descriptor; 2632 2633 /* Setup to transfer xfer_size bytes to device */ 2634 host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64; 2635 host_buffer->buffer_length = desired_write_length; 2636 host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys); 2637 host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys); 2638 2639 return(sli_config_off + sizeof(sli4_req_common_write_object_t) + sizeof (sli4_bde_t)); 2640 } 2641 2642 /** 2643 * @ingroup sli 2644 * @brief Write a COMMON_DELETE_OBJECT command. 2645 * 2646 * @param sli4 SLI context. 2647 * @param buf Destination buffer for the command. 2648 * @param size Buffer size, in bytes. 2649 * @param object_name Name of the object to write. 2650 * 2651 * @return Returns the number of bytes written. 2652 */ 2653 int32_t 2654 sli_cmd_common_delete_object(sli4_t *sli4, void *buf, size_t size, 2655 char *object_name) 2656 { 2657 sli4_req_common_delete_object_t *del_obj = NULL; 2658 uint32_t sli_config_off = 0; 2659 2660 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2661 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2662 sizeof (sli4_req_common_delete_object_t), 2663 NULL); 2664 } 2665 2666 del_obj = (sli4_req_common_delete_object_t *)((uint8_t *)buf + sli_config_off); 2667 2668 del_obj->hdr.opcode = SLI4_OPC_COMMON_DELETE_OBJECT; 2669 del_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2670 del_obj->hdr.request_length = sizeof(*del_obj); 2671 del_obj->hdr.timeout = 0; 2672 del_obj->hdr.version = 0; 2673 2674 ocs_strncpy(del_obj->object_name, object_name, sizeof(del_obj->object_name)); 2675 return(sli_config_off + sizeof(sli4_req_common_delete_object_t)); 2676 } 2677 2678 /** 2679 * @ingroup sli 2680 * @brief Write a COMMON_READ_OBJECT command. 2681 * 2682 * @param sli4 SLI context. 2683 * @param buf Destination buffer for the command. 2684 * @param size Buffer size, in bytes. 2685 * @param desired_read_length Number of bytes of data to read from the object. 2686 * @param offset Offset, in bytes, from the start of the object. 2687 * @param object_name Name of the object to read. 2688 * @param dma DMA structure from which the data will be copied. 2689 * 2690 * @return Returns the number of bytes written. 2691 */ 2692 int32_t 2693 sli_cmd_common_read_object(sli4_t *sli4, void *buf, size_t size, 2694 uint32_t desired_read_length, 2695 uint32_t offset, 2696 char *object_name, 2697 ocs_dma_t *dma) 2698 { 2699 sli4_req_common_read_object_t *rd_obj = NULL; 2700 uint32_t sli_config_off = 0; 2701 sli4_bde_t *host_buffer; 2702 2703 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2704 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2705 sizeof (sli4_req_common_read_object_t) + sizeof (sli4_bde_t), 2706 NULL); 2707 } 2708 2709 rd_obj = (sli4_req_common_read_object_t *)((uint8_t *)buf + sli_config_off); 2710 2711 rd_obj->hdr.opcode = SLI4_OPC_COMMON_READ_OBJECT; 2712 rd_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2713 rd_obj->hdr.request_length = sizeof(*rd_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t); 2714 rd_obj->hdr.timeout = 0; 2715 rd_obj->hdr.version = 0; 2716 2717 rd_obj->desired_read_length = desired_read_length; 2718 rd_obj->read_offset = offset; 2719 ocs_strncpy(rd_obj->object_name, object_name, sizeof(rd_obj->object_name)); 2720 rd_obj->host_buffer_descriptor_count = 1; 2721 2722 host_buffer = (sli4_bde_t *)rd_obj->host_buffer_descriptor; 2723 2724 /* Setup to transfer xfer_size bytes to device */ 2725 host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64; 2726 host_buffer->buffer_length = desired_read_length; 2727 if (dma != NULL) { 2728 host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys); 2729 host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys); 2730 } else { 2731 host_buffer->u.data.buffer_address_low = 0; 2732 host_buffer->u.data.buffer_address_high = 0; 2733 } 2734 2735 return(sli_config_off + sizeof(sli4_req_common_read_object_t) + sizeof (sli4_bde_t)); 2736 } 2737 2738 /** 2739 * @ingroup sli 2740 * @brief Write a DMTF_EXEC_CLP_CMD command. 2741 * 2742 * @param sli4 SLI context. 2743 * @param buf Destination buffer for the command. 2744 * @param size Buffer size, in bytes. 2745 * @param cmd DMA structure that describes the buffer for the command. 2746 * @param resp DMA structure that describes the buffer for the response. 2747 * 2748 * @return Returns the number of bytes written. 2749 */ 2750 int32_t 2751 sli_cmd_dmtf_exec_clp_cmd(sli4_t *sli4, void *buf, size_t size, 2752 ocs_dma_t *cmd, 2753 ocs_dma_t *resp) 2754 { 2755 sli4_req_dmtf_exec_clp_cmd_t *clp_cmd = NULL; 2756 uint32_t sli_config_off = 0; 2757 2758 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2759 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2760 sizeof (sli4_req_dmtf_exec_clp_cmd_t), 2761 NULL); 2762 } 2763 2764 clp_cmd = (sli4_req_dmtf_exec_clp_cmd_t*)((uint8_t *)buf + sli_config_off); 2765 2766 clp_cmd->hdr.opcode = SLI4_OPC_DMTF_EXEC_CLP_CMD; 2767 clp_cmd->hdr.subsystem = SLI4_SUBSYSTEM_DMTF; 2768 clp_cmd->hdr.request_length = sizeof(sli4_req_dmtf_exec_clp_cmd_t) - 2769 sizeof(sli4_req_hdr_t); 2770 clp_cmd->hdr.timeout = 0; 2771 clp_cmd->hdr.version = 0; 2772 clp_cmd->cmd_buf_length = cmd->size; 2773 clp_cmd->cmd_buf_addr_low = ocs_addr32_lo(cmd->phys); 2774 clp_cmd->cmd_buf_addr_high = ocs_addr32_hi(cmd->phys); 2775 clp_cmd->resp_buf_length = resp->size; 2776 clp_cmd->resp_buf_addr_low = ocs_addr32_lo(resp->phys); 2777 clp_cmd->resp_buf_addr_high = ocs_addr32_hi(resp->phys); 2778 2779 return(sli_config_off + sizeof(sli4_req_dmtf_exec_clp_cmd_t)); 2780 } 2781 2782 /** 2783 * @ingroup sli 2784 * @brief Write a COMMON_SET_DUMP_LOCATION command. 2785 * 2786 * @param sli4 SLI context. 2787 * @param buf Destination buffer for the command. 2788 * @param size Buffer size, in bytes. 2789 * @param query Zero to set dump location, non-zero to query dump size 2790 * @param is_buffer_list Set to one if the buffer is a set of buffer descriptors or 2791 * set to 0 if the buffer is a contiguous dump area. 2792 * @param buffer DMA structure to which the dump will be copied. 2793 * 2794 * @return Returns the number of bytes written. 2795 */ 2796 int32_t 2797 sli_cmd_common_set_dump_location(sli4_t *sli4, void *buf, size_t size, 2798 uint8_t query, uint8_t is_buffer_list, 2799 ocs_dma_t *buffer, uint8_t fdb) 2800 { 2801 sli4_req_common_set_dump_location_t *set_dump_loc = NULL; 2802 uint32_t sli_config_off = 0; 2803 2804 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2805 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2806 sizeof (sli4_req_common_set_dump_location_t), 2807 NULL); 2808 } 2809 2810 set_dump_loc = (sli4_req_common_set_dump_location_t *)((uint8_t *)buf + sli_config_off); 2811 2812 set_dump_loc->hdr.opcode = SLI4_OPC_COMMON_SET_DUMP_LOCATION; 2813 set_dump_loc->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2814 set_dump_loc->hdr.request_length = sizeof(sli4_req_common_set_dump_location_t) - sizeof(sli4_req_hdr_t); 2815 set_dump_loc->hdr.timeout = 0; 2816 set_dump_loc->hdr.version = 0; 2817 2818 set_dump_loc->blp = is_buffer_list; 2819 set_dump_loc->qry = query; 2820 set_dump_loc->fdb = fdb; 2821 2822 if (buffer) { 2823 set_dump_loc->buf_addr_low = ocs_addr32_lo(buffer->phys); 2824 set_dump_loc->buf_addr_high = ocs_addr32_hi(buffer->phys); 2825 set_dump_loc->buffer_length = buffer->len; 2826 } else { 2827 set_dump_loc->buf_addr_low = 0; 2828 set_dump_loc->buf_addr_high = 0; 2829 set_dump_loc->buffer_length = 0; 2830 } 2831 2832 return(sli_config_off + sizeof(sli4_req_common_set_dump_location_t)); 2833 } 2834 2835 /** 2836 * @ingroup sli 2837 * @brief Write a COMMON_SET_FEATURES command. 2838 * 2839 * @param sli4 SLI context. 2840 * @param buf Destination buffer for the command. 2841 * @param size Buffer size, in bytes. 2842 * @param feature Feature to set. 2843 * @param param_len Length of the parameter (must be a multiple of 4 bytes). 2844 * @param parameter Pointer to the parameter value. 2845 * 2846 * @return Returns the number of bytes written. 2847 */ 2848 int32_t 2849 sli_cmd_common_set_features(sli4_t *sli4, void *buf, size_t size, 2850 uint32_t feature, 2851 uint32_t param_len, 2852 void* parameter) 2853 { 2854 sli4_req_common_set_features_t *cmd = NULL; 2855 uint32_t sli_config_off = 0; 2856 2857 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2858 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2859 sizeof (sli4_req_common_set_features_t), 2860 NULL); 2861 } 2862 2863 cmd = (sli4_req_common_set_features_t *)((uint8_t *)buf + sli_config_off); 2864 2865 cmd->hdr.opcode = SLI4_OPC_COMMON_SET_FEATURES; 2866 cmd->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2867 cmd->hdr.request_length = sizeof(sli4_req_common_set_features_t) - sizeof(sli4_req_hdr_t); 2868 cmd->hdr.timeout = 0; 2869 cmd->hdr.version = 0; 2870 2871 cmd->feature = feature; 2872 cmd->param_len = param_len; 2873 ocs_memcpy(cmd->params, parameter, param_len); 2874 2875 return(sli_config_off + sizeof(sli4_req_common_set_features_t)); 2876 } 2877 2878 /** 2879 * @ingroup sli 2880 * @brief Write a COMMON_COMMON_GET_PROFILE_CONFIG command. 2881 * 2882 * @param sli4 SLI context. 2883 * @param buf Destination buffer for the command. 2884 * @param size Buffer size in bytes. 2885 * @param dma DMA capable memory used to retrieve profile. 2886 * 2887 * @return Returns the number of bytes written. 2888 */ 2889 int32_t 2890 sli_cmd_common_get_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma) 2891 { 2892 sli4_req_common_get_profile_config_t *req = NULL; 2893 uint32_t sli_config_off = 0; 2894 uint32_t payload_size; 2895 2896 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2897 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 2898 sizeof (sli4_req_common_get_profile_config_t), 2899 dma); 2900 } 2901 2902 if (dma != NULL) { 2903 req = dma->virt; 2904 ocs_memset(req, 0, dma->size); 2905 payload_size = dma->size; 2906 } else { 2907 req = (sli4_req_common_get_profile_config_t *)((uint8_t *)buf + sli_config_off); 2908 payload_size = sizeof(sli4_req_common_get_profile_config_t); 2909 } 2910 2911 req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_CONFIG; 2912 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2913 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 2914 req->hdr.version = 1; 2915 2916 return(sli_config_off + sizeof(sli4_req_common_get_profile_config_t)); 2917 } 2918 2919 /** 2920 * @ingroup sli 2921 * @brief Write a COMMON_COMMON_SET_PROFILE_CONFIG command. 2922 * 2923 * @param sli4 SLI context. 2924 * @param buf Destination buffer for the command. 2925 * @param size Buffer size, in bytes. 2926 * @param dma DMA capable memory containing profile. 2927 * @param profile_id Profile ID to configure. 2928 * @param descriptor_count Number of descriptors in DMA buffer. 2929 * @param isap Implicit Set Active Profile value to use. 2930 * 2931 * @return Returns the number of bytes written. 2932 */ 2933 int32_t 2934 sli_cmd_common_set_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, 2935 uint8_t profile_id, uint32_t descriptor_count, uint8_t isap) 2936 { 2937 sli4_req_common_set_profile_config_t *req = NULL; 2938 uint32_t cmd_off = 0; 2939 uint32_t payload_size; 2940 2941 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2942 cmd_off = sli_cmd_sli_config(sli4, buf, size, 2943 sizeof (sli4_req_common_set_profile_config_t), 2944 dma); 2945 } 2946 2947 if (dma != NULL) { 2948 req = dma->virt; 2949 ocs_memset(req, 0, dma->size); 2950 payload_size = dma->size; 2951 } else { 2952 req = (sli4_req_common_set_profile_config_t *)((uint8_t *)buf + cmd_off); 2953 payload_size = sizeof(sli4_req_common_set_profile_config_t); 2954 } 2955 2956 req->hdr.opcode = SLI4_OPC_COMMON_SET_PROFILE_CONFIG; 2957 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 2958 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 2959 req->hdr.version = 1; 2960 req->profile_id = profile_id; 2961 req->desc_count = descriptor_count; 2962 req->isap = isap; 2963 2964 return(cmd_off + sizeof(sli4_req_common_set_profile_config_t)); 2965 } 2966 2967 /** 2968 * @ingroup sli 2969 * @brief Write a COMMON_COMMON_GET_PROFILE_LIST command. 2970 * 2971 * @param sli4 SLI context. 2972 * @param buf Destination buffer for the command. 2973 * @param size Buffer size in bytes. 2974 * @param start_profile_index First profile index to return. 2975 * @param dma Buffer into which the list will be written. 2976 * 2977 * @return Returns the number of bytes written. 2978 */ 2979 int32_t 2980 sli_cmd_common_get_profile_list(sli4_t *sli4, void *buf, size_t size, 2981 uint32_t start_profile_index, ocs_dma_t *dma) 2982 { 2983 sli4_req_common_get_profile_list_t *req = NULL; 2984 uint32_t cmd_off = 0; 2985 uint32_t payload_size; 2986 2987 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 2988 cmd_off = sli_cmd_sli_config(sli4, buf, size, 2989 sizeof (sli4_req_common_get_profile_list_t), 2990 dma); 2991 } 2992 2993 if (dma != NULL) { 2994 req = dma->virt; 2995 ocs_memset(req, 0, dma->size); 2996 payload_size = dma->size; 2997 } else { 2998 req = (sli4_req_common_get_profile_list_t *)((uint8_t *)buf + cmd_off); 2999 payload_size = sizeof(sli4_req_common_get_profile_list_t); 3000 } 3001 3002 req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_LIST; 3003 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 3004 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 3005 req->hdr.version = 0; 3006 3007 req->start_profile_index = start_profile_index; 3008 3009 return(cmd_off + sizeof(sli4_req_common_get_profile_list_t)); 3010 } 3011 3012 /** 3013 * @ingroup sli 3014 * @brief Write a COMMON_COMMON_GET_ACTIVE_PROFILE command. 3015 * 3016 * @param sli4 SLI context. 3017 * @param buf Destination buffer for the command. 3018 * @param size Buffer size in bytes. 3019 * 3020 * @return Returns the number of bytes written. 3021 */ 3022 int32_t 3023 sli_cmd_common_get_active_profile(sli4_t *sli4, void *buf, size_t size) 3024 { 3025 sli4_req_common_get_active_profile_t *req = NULL; 3026 uint32_t cmd_off = 0; 3027 uint32_t payload_size; 3028 3029 /* Payload length must accommodate both request and response */ 3030 payload_size = max(sizeof(sli4_req_common_get_active_profile_t), 3031 sizeof(sli4_res_common_get_active_profile_t)); 3032 3033 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 3034 cmd_off = sli_cmd_sli_config(sli4, buf, size, 3035 payload_size, 3036 NULL); 3037 } 3038 3039 req = (sli4_req_common_get_active_profile_t *) 3040 ((uint8_t*)buf + cmd_off); 3041 3042 req->hdr.opcode = SLI4_OPC_COMMON_GET_ACTIVE_PROFILE; 3043 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 3044 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 3045 req->hdr.version = 0; 3046 3047 return(cmd_off + sizeof(sli4_req_common_get_active_profile_t)); 3048 } 3049 3050 /** 3051 * @ingroup sli 3052 * @brief Write a COMMON_COMMON_SET_ACTIVE_PROFILE command. 3053 * 3054 * @param sli4 SLI context. 3055 * @param buf Destination buffer for the command. 3056 * @param size Buffer size in bytes. 3057 * @param fd If non-zero, set profile to factory default. 3058 * @param active_profile_id ID of new active profile. 3059 * 3060 * @return Returns the number of bytes written. 3061 */ 3062 int32_t 3063 sli_cmd_common_set_active_profile(sli4_t *sli4, void *buf, size_t size, 3064 uint32_t fd, uint32_t active_profile_id) 3065 { 3066 sli4_req_common_set_active_profile_t *req = NULL; 3067 uint32_t cmd_off = 0; 3068 uint32_t payload_size; 3069 3070 /* Payload length must accommodate both request and response */ 3071 payload_size = max(sizeof(sli4_req_common_set_active_profile_t), 3072 sizeof(sli4_res_common_set_active_profile_t)); 3073 3074 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 3075 cmd_off = sli_cmd_sli_config(sli4, buf, size, 3076 payload_size, 3077 NULL); 3078 } 3079 3080 req = (sli4_req_common_set_active_profile_t *) 3081 ((uint8_t*)buf + cmd_off); 3082 3083 req->hdr.opcode = SLI4_OPC_COMMON_SET_ACTIVE_PROFILE; 3084 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 3085 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 3086 req->hdr.version = 0; 3087 req->fd = fd; 3088 req->active_profile_id = active_profile_id; 3089 3090 return(cmd_off + sizeof(sli4_req_common_set_active_profile_t)); 3091 } 3092 3093 /** 3094 * @ingroup sli 3095 * @brief Write a COMMON_GET_RECONFIG_LINK_INFO command. 3096 * 3097 * @param sli4 SLI context. 3098 * @param buf Destination buffer for the command. 3099 * @param size Buffer size in bytes. 3100 * @param dma Buffer to store the supported link configuration modes from the physical device. 3101 * 3102 * @return Returns the number of bytes written. 3103 */ 3104 int32_t 3105 sli_cmd_common_get_reconfig_link_info(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma) 3106 { 3107 sli4_req_common_get_reconfig_link_info_t *req = NULL; 3108 uint32_t cmd_off = 0; 3109 uint32_t payload_size; 3110 3111 /* Payload length must accommodate both request and response */ 3112 payload_size = max(sizeof(sli4_req_common_get_reconfig_link_info_t), 3113 sizeof(sli4_res_common_get_reconfig_link_info_t)); 3114 3115 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 3116 cmd_off = sli_cmd_sli_config(sli4, buf, size, 3117 payload_size, 3118 dma); 3119 } 3120 3121 if (dma != NULL) { 3122 req = dma->virt; 3123 ocs_memset(req, 0, dma->size); 3124 payload_size = dma->size; 3125 } else { 3126 req = (sli4_req_common_get_reconfig_link_info_t *)((uint8_t *)buf + cmd_off); 3127 payload_size = sizeof(sli4_req_common_get_reconfig_link_info_t); 3128 } 3129 3130 req->hdr.opcode = SLI4_OPC_COMMON_GET_RECONFIG_LINK_INFO; 3131 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 3132 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 3133 req->hdr.version = 0; 3134 3135 return(cmd_off + sizeof(sli4_req_common_get_reconfig_link_info_t)); 3136 } 3137 3138 /** 3139 * @ingroup sli 3140 * @brief Write a COMMON_SET_RECONFIG_LINK_ID command. 3141 * 3142 * @param sli4 SLI context. 3143 * @param buf destination buffer for the command. 3144 * @param size buffer size in bytes. 3145 * @param fd If non-zero, set link config to factory default. 3146 * @param active_link_config_id ID of new active profile. 3147 * @param dma Buffer to assign the link configuration mode that is to become active from the physical device. 3148 * 3149 * @return Returns the number of bytes written. 3150 */ 3151 int32_t 3152 sli_cmd_common_set_reconfig_link_id(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, 3153 uint32_t fd, uint32_t active_link_config_id) 3154 { 3155 sli4_req_common_set_reconfig_link_id_t *req = NULL; 3156 uint32_t cmd_off = 0; 3157 uint32_t payload_size; 3158 3159 /* Payload length must accommodate both request and response */ 3160 payload_size = max(sizeof(sli4_req_common_set_reconfig_link_id_t), 3161 sizeof(sli4_res_common_set_reconfig_link_id_t)); 3162 3163 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 3164 cmd_off = sli_cmd_sli_config(sli4, buf, size, 3165 payload_size, 3166 NULL); 3167 } 3168 3169 if (dma != NULL) { 3170 req = dma->virt; 3171 ocs_memset(req, 0, dma->size); 3172 payload_size = dma->size; 3173 } else { 3174 req = (sli4_req_common_set_reconfig_link_id_t *)((uint8_t *)buf + cmd_off); 3175 payload_size = sizeof(sli4_req_common_set_reconfig_link_id_t); 3176 } 3177 3178 req->hdr.opcode = SLI4_OPC_COMMON_SET_RECONFIG_LINK_ID; 3179 req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON; 3180 req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t); 3181 req->hdr.version = 0; 3182 req->fd = fd; 3183 req->next_link_config_id = active_link_config_id; 3184 3185 return(cmd_off + sizeof(sli4_req_common_set_reconfig_link_id_t)); 3186 } 3187 3188 /** 3189 * @ingroup sli 3190 * @brief Check the mailbox/queue completion entry. 3191 * 3192 * @param buf Pointer to the MCQE. 3193 * 3194 * @return Returns 0 on success, or a non-zero value on failure. 3195 */ 3196 int32_t 3197 sli_cqe_mq(void *buf) 3198 { 3199 sli4_mcqe_t *mcqe = buf; 3200 3201 /* 3202 * Firmware can split mbx completions into two MCQEs: first with only 3203 * the "consumed" bit set and a second with the "complete" bit set. 3204 * Thus, ignore MCQE unless "complete" is set. 3205 */ 3206 if (!mcqe->cmp) { 3207 return -2; 3208 } 3209 3210 if (mcqe->completion_status) { 3211 ocs_log_debug(NULL, "bad status (cmpl=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n", 3212 mcqe->completion_status, 3213 mcqe->extended_status, 3214 mcqe->con, 3215 mcqe->cmp, 3216 mcqe->ae, 3217 mcqe->val); 3218 } 3219 3220 return mcqe->completion_status; 3221 } 3222 3223 /** 3224 * @ingroup sli 3225 * @brief Check the asynchronous event completion entry. 3226 * 3227 * @param sli4 SLI context. 3228 * @param buf Pointer to the ACQE. 3229 * 3230 * @return Returns 0 on success, or a non-zero value on failure. 3231 */ 3232 int32_t 3233 sli_cqe_async(sli4_t *sli4, void *buf) 3234 { 3235 sli4_acqe_t *acqe = buf; 3236 int32_t rc = -1; 3237 3238 if (!sli4 || !buf) { 3239 ocs_log_err(NULL, "bad parameter sli4=%p buf=%p\n", sli4, buf); 3240 return -1; 3241 } 3242 3243 switch (acqe->event_code) { 3244 case SLI4_ACQE_EVENT_CODE_LINK_STATE: 3245 rc = sli_fc_process_link_state(sli4, buf); 3246 break; 3247 case SLI4_ACQE_EVENT_CODE_FCOE_FIP: 3248 rc = sli_fc_process_fcoe(sli4, buf); 3249 break; 3250 case SLI4_ACQE_EVENT_CODE_GRP_5: 3251 /*TODO*/ocs_log_debug(sli4->os, "ACQE GRP5\n"); 3252 break; 3253 case SLI4_ACQE_EVENT_CODE_SLI_PORT_EVENT: 3254 ocs_log_debug(sli4->os,"ACQE SLI Port, type=0x%x, data1,2=0x%08x,0x%08x\n", 3255 acqe->event_type, acqe->event_data[0], acqe->event_data[1]); 3256 #if defined(OCS_INCLUDE_DEBUG) 3257 ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "acq", acqe, sizeof(*acqe)); 3258 #endif 3259 break; 3260 case SLI4_ACQE_EVENT_CODE_FC_LINK_EVENT: 3261 rc = sli_fc_process_link_attention(sli4, buf); 3262 break; 3263 default: 3264 /*TODO*/ocs_log_test(sli4->os, "ACQE unknown=%#x\n", acqe->event_code); 3265 } 3266 3267 return rc; 3268 } 3269 3270 /** 3271 * @brief Check the SLI_CONFIG response. 3272 * 3273 * @par Description 3274 * Function checks the SLI_CONFIG response and the payload status. 3275 * 3276 * @param buf Pointer to SLI_CONFIG response. 3277 * 3278 * @return Returns 0 on success, or a non-zero value on failure. 3279 */ 3280 static int32_t 3281 sli_res_sli_config(void *buf) 3282 { 3283 sli4_cmd_sli_config_t *sli_config = buf; 3284 3285 if (!buf || (SLI4_MBOX_COMMAND_SLI_CONFIG != sli_config->hdr.command)) { 3286 ocs_log_err(NULL, "bad parameter buf=%p cmd=%#x\n", buf, 3287 buf ? sli_config->hdr.command : -1); 3288 return -1; 3289 } 3290 3291 if (sli_config->hdr.status) { 3292 return sli_config->hdr.status; 3293 } 3294 3295 if (sli_config->emb) { 3296 return sli_config->payload.embed[4]; 3297 } else { 3298 ocs_log_test(NULL, "external buffers not supported\n"); 3299 return -1; 3300 } 3301 } 3302 3303 /** 3304 * @brief Issue a COMMON_FUNCTION_RESET command. 3305 * 3306 * @param sli4 SLI context. 3307 * 3308 * @return Returns 0 on success, or a non-zero value on failure. 3309 */ 3310 static int32_t 3311 sli_common_function_reset(sli4_t *sli4) 3312 { 3313 3314 if (sli_cmd_common_function_reset(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 3315 if (sli_bmbx_command(sli4)) { 3316 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COM_FUNC_RESET)\n"); 3317 return -1; 3318 } 3319 if (sli_res_sli_config(sli4->bmbx.virt)) { 3320 ocs_log_err(sli4->os, "bad status COM_FUNC_RESET\n"); 3321 return -1; 3322 } 3323 } else { 3324 ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n"); 3325 return -1; 3326 } 3327 3328 return 0; 3329 } 3330 3331 /** 3332 * @brief check to see if the FW is ready. 3333 * 3334 * @par Description 3335 * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>. 3336 * 3337 * @param sli4 SLI context. 3338 * @param timeout_ms Time, in milliseconds, to wait for the port to be ready 3339 * before failing. 3340 * 3341 * @return Returns TRUE for ready, or FALSE otherwise. 3342 */ 3343 static int32_t 3344 sli_wait_for_fw_ready(sli4_t *sli4, uint32_t timeout_ms) 3345 { 3346 uint32_t iter = timeout_ms / (SLI4_INIT_PORT_DELAY_US / 1000); 3347 uint32_t ready = FALSE; 3348 3349 do { 3350 iter--; 3351 ocs_udelay(SLI4_INIT_PORT_DELAY_US); 3352 if (sli_fw_ready(sli4) == 1) { 3353 ready = TRUE; 3354 } 3355 } while (!ready && (iter > 0)); 3356 3357 return ready; 3358 } 3359 3360 /** 3361 * @brief Initialize the firmware. 3362 * 3363 * @par Description 3364 * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>. 3365 * 3366 * @param sli4 SLI context. 3367 * 3368 * @return Returns 0 on success, or a non-zero value on failure. 3369 */ 3370 static int32_t 3371 sli_fw_init(sli4_t *sli4) 3372 { 3373 uint32_t ready; 3374 uint32_t endian; 3375 3376 /* 3377 * Is firmware ready for operation? 3378 */ 3379 ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC); 3380 if (!ready) { 3381 ocs_log_crit(sli4->os, "FW status is NOT ready\n"); 3382 return -1; 3383 } 3384 3385 /* 3386 * Reset port to a known state 3387 */ 3388 switch (sli4->if_type) { 3389 case SLI4_IF_TYPE_BE3_SKH_PF: 3390 case SLI4_IF_TYPE_BE3_SKH_VF: 3391 /* No SLIPORT_CONTROL register so use command sequence instead */ 3392 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) { 3393 ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n"); 3394 return -1; 3395 } 3396 3397 if (sli_cmd_fw_initialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 3398 if (sli_bmbx_command(sli4)) { 3399 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_INIT)\n"); 3400 return -1; 3401 } 3402 } else { 3403 ocs_log_crit(sli4->os, "bad FW_INIT write\n"); 3404 return -1; 3405 } 3406 3407 if (sli_common_function_reset(sli4)) { 3408 ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n"); 3409 return -1; 3410 } 3411 break; 3412 case SLI4_IF_TYPE_LANCER_FC_ETH: 3413 case SLI4_IF_TYPE_LANCER_G7: 3414 #if BYTE_ORDER == LITTLE_ENDIAN 3415 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN; 3416 #else 3417 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN; 3418 #endif 3419 3420 if (sli_sliport_control(sli4, endian)) 3421 return -1; 3422 break; 3423 default: 3424 ocs_log_test(sli4->os, "if_type %d not supported\n", sli4->if_type); 3425 return -1; 3426 } 3427 3428 return 0; 3429 } 3430 3431 /** 3432 * @brief Terminate the firmware. 3433 * 3434 * @param sli4 SLI context. 3435 * 3436 * @return Returns 0 on success, or a non-zero value on failure. 3437 */ 3438 static int32_t 3439 sli_fw_term(sli4_t *sli4) 3440 { 3441 uint32_t endian; 3442 3443 if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF || 3444 sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF) { 3445 /* No SLIPORT_CONTROL register so use command sequence instead */ 3446 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) { 3447 ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n"); 3448 return -1; 3449 } 3450 3451 if (sli_common_function_reset(sli4)) { 3452 ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n"); 3453 return -1; 3454 } 3455 3456 if (sli_cmd_fw_deinitialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 3457 if (sli_bmbx_command(sli4)) { 3458 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_DEINIT)\n"); 3459 return -1; 3460 } 3461 } else { 3462 ocs_log_test(sli4->os, "bad FW_DEINIT write\n"); 3463 return -1; 3464 } 3465 } else { 3466 #if BYTE_ORDER == LITTLE_ENDIAN 3467 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN; 3468 #else 3469 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN; 3470 #endif 3471 /* type 2 etc. use SLIPORT_CONTROL to initialize port */ 3472 sli_sliport_control(sli4, endian); 3473 } 3474 return 0; 3475 } 3476 3477 /** 3478 * @brief Write the doorbell register associated with the queue object. 3479 * 3480 * @param sli4 SLI context. 3481 * @param q Queue object. 3482 * 3483 * @return Returns 0 on success, or a non-zero value on failure. 3484 */ 3485 static int32_t 3486 sli_queue_doorbell(sli4_t *sli4, sli4_queue_t *q) 3487 { 3488 uint32_t val = 0; 3489 3490 switch (q->type) { 3491 case SLI_QTYPE_EQ: 3492 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) 3493 val = sli_iftype6_eq_doorbell(q->n_posted, q->id, FALSE); 3494 else 3495 val = sli_eq_doorbell(q->n_posted, q->id, FALSE); 3496 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 3497 break; 3498 case SLI_QTYPE_CQ: 3499 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) 3500 val = sli_iftype6_cq_doorbell(q->n_posted, q->id, FALSE); 3501 else 3502 val = sli_cq_doorbell(q->n_posted, q->id, FALSE); 3503 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 3504 break; 3505 case SLI_QTYPE_MQ: 3506 val = SLI4_MQ_DOORBELL(q->n_posted, q->id); 3507 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 3508 break; 3509 case SLI_QTYPE_RQ: 3510 { 3511 uint32_t n_posted = q->n_posted; 3512 /* 3513 * FC/FCoE has different rules for Receive Queues. The host 3514 * should only update the doorbell of the RQ-pair containing 3515 * the headers since the header / payload RQs are treated 3516 * as a matched unit. 3517 */ 3518 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 3519 /* 3520 * In RQ-pair, an RQ either contains the FC header 3521 * (i.e. is_hdr == TRUE) or the payload. 3522 * 3523 * Don't ring doorbell for payload RQ 3524 */ 3525 if (!q->u.flag.is_hdr) { 3526 break; 3527 } 3528 /* 3529 * Some RQ cannot be incremented one entry at a time. Instead, 3530 * the driver collects a number of entries and updates the 3531 * RQ in batches. 3532 */ 3533 if (q->u.flag.rq_batch) { 3534 if (((q->index + q->n_posted) % SLI4_QUEUE_RQ_BATCH)) { 3535 break; 3536 } 3537 n_posted = SLI4_QUEUE_RQ_BATCH; 3538 } 3539 } 3540 3541 val = SLI4_RQ_DOORBELL(n_posted, q->id); 3542 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 3543 break; 3544 } 3545 case SLI_QTYPE_WQ: 3546 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) { 3547 val = SLI4_WQ_DOORBELL(q->n_posted, 0, q->id); 3548 } else { 3549 /* For iftype = 2 and 3, q->index value is ignored */ 3550 val = SLI4_WQ_DOORBELL(q->n_posted, q->index, q->id); 3551 } 3552 3553 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 3554 break; 3555 default: 3556 ocs_log_test(sli4->os, "bad queue type %d\n", q->type); 3557 return -1; 3558 } 3559 3560 return 0; 3561 } 3562 3563 static int32_t 3564 sli_request_features(sli4_t *sli4, sli4_features_t *features, uint8_t query) 3565 { 3566 3567 if (sli_cmd_request_features(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 3568 *features, query)) { 3569 sli4_cmd_request_features_t *req_features = sli4->bmbx.virt; 3570 3571 if (sli_bmbx_command(sli4)) { 3572 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (REQUEST_FEATURES)\n"); 3573 return -1; 3574 } 3575 if (req_features->hdr.status) { 3576 ocs_log_err(sli4->os, "REQUEST_FEATURES bad status %#x\n", 3577 req_features->hdr.status); 3578 return -1; 3579 } 3580 features->dword = req_features->response.dword; 3581 } else { 3582 ocs_log_err(sli4->os, "bad REQUEST_FEATURES write\n"); 3583 return -1; 3584 } 3585 3586 return 0; 3587 } 3588 3589 /** 3590 * @brief Calculate max queue entries. 3591 * 3592 * @param sli4 SLI context. 3593 * 3594 * @return Returns 0 on success, or a non-zero value on failure. 3595 */ 3596 void 3597 sli_calc_max_qentries(sli4_t *sli4) 3598 { 3599 sli4_qtype_e q; 3600 uint32_t alloc_size, qentries, qentry_size; 3601 3602 for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) { 3603 sli4->config.max_qentries[q] = sli_convert_mask_to_count(sli4->config.count_method[q], 3604 sli4->config.count_mask[q]); 3605 } 3606 3607 /* single, continguous DMA allocations will be called for each queue 3608 * of size (max_qentries * queue entry size); since these can be large, 3609 * check against the OS max DMA allocation size 3610 */ 3611 for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) { 3612 qentries = sli4->config.max_qentries[q]; 3613 qentry_size = sli_get_queue_entry_size(sli4, q); 3614 alloc_size = qentries * qentry_size; 3615 if (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) { 3616 while (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) { 3617 /* cut the qentries in hwf until alloc_size <= max DMA alloc size */ 3618 qentries >>= 1; 3619 alloc_size = qentries * qentry_size; 3620 } 3621 ocs_log_debug(sli4->os, "[%s]: max_qentries from %d to %d (max dma %d)\n", 3622 SLI_QNAME[q], sli4->config.max_qentries[q], 3623 qentries, ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)); 3624 sli4->config.max_qentries[q] = qentries; 3625 } 3626 } 3627 } 3628 3629 /** 3630 * @brief Issue a FW_CONFIG mailbox command and store the results. 3631 * 3632 * @param sli4 SLI context. 3633 * 3634 * @return Returns 0 on success, or a non-zero value on failure. 3635 */ 3636 static int32_t 3637 sli_query_fw_config(sli4_t *sli4) 3638 { 3639 /* 3640 * Read the device configuration 3641 * 3642 * Note: Only ulp0 fields contain values 3643 */ 3644 if (sli_cmd_common_query_fw_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 3645 sli4_res_common_query_fw_config_t *fw_config = 3646 (sli4_res_common_query_fw_config_t *) 3647 (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed)); 3648 3649 if (sli_bmbx_command(sli4)) { 3650 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (QUERY_FW_CONFIG)\n"); 3651 return -1; 3652 } 3653 if (fw_config->hdr.status) { 3654 ocs_log_err(sli4->os, "COMMON_QUERY_FW_CONFIG bad status %#x\n", 3655 fw_config->hdr.status); 3656 return -1; 3657 } 3658 3659 sli4->physical_port = fw_config->physical_port; 3660 sli4->config.dual_ulp_capable = ((fw_config->function_mode & SLI4_FUNCTION_MODE_DUA_MODE) == 0 ? 0 : 1); 3661 sli4->config.is_ulp_fc[0] = ((fw_config->ulp0_mode & 3662 (SLI4_ULP_MODE_FCOE_INI | 3663 SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1); 3664 sli4->config.is_ulp_fc[1] = ((fw_config->ulp1_mode & 3665 (SLI4_ULP_MODE_FCOE_INI | 3666 SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1); 3667 3668 if (sli4->config.dual_ulp_capable) { 3669 /* 3670 * Lancer will not support this, so we use the values 3671 * from the READ_CONFIG. 3672 */ 3673 if (sli4->config.is_ulp_fc[0] && 3674 sli4->config.is_ulp_fc[1]) { 3675 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total + fw_config->ulp1_toe_wq_total; 3676 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total + fw_config->ulp1_toe_defrq_total; 3677 } else if (sli4->config.is_ulp_fc[0]) { 3678 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total; 3679 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total; 3680 } else { 3681 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp1_toe_wq_total; 3682 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp1_toe_defrq_total; 3683 } 3684 } 3685 } else { 3686 ocs_log_err(sli4->os, "bad QUERY_FW_CONFIG write\n"); 3687 return -1; 3688 } 3689 return 0; 3690 } 3691 3692 static int32_t 3693 sli_get_config(sli4_t *sli4) 3694 { 3695 ocs_dma_t get_cntl_addl_data; 3696 3697 /* 3698 * Read the device configuration 3699 */ 3700 if (sli_cmd_read_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 3701 sli4_res_read_config_t *read_config = sli4->bmbx.virt; 3702 uint32_t i; 3703 uint32_t total; 3704 3705 if (sli_bmbx_command(sli4)) { 3706 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_CONFIG)\n"); 3707 return -1; 3708 } 3709 if (read_config->hdr.status) { 3710 ocs_log_err(sli4->os, "READ_CONFIG bad status %#x\n", 3711 read_config->hdr.status); 3712 return -1; 3713 } 3714 3715 sli4->config.has_extents = read_config->ext; 3716 if (FALSE == sli4->config.has_extents) { 3717 uint32_t i = 0; 3718 uint32_t *base = sli4->config.extent[0].base; 3719 3720 if (!base) { 3721 if (NULL == (base = ocs_malloc(sli4->os, SLI_RSRC_MAX * sizeof(uint32_t), 3722 OCS_M_ZERO | OCS_M_NOWAIT))) { 3723 ocs_log_err(sli4->os, "memory allocation failed for sli4_resource_t\n"); 3724 return -1; 3725 } 3726 } 3727 3728 for (i = 0; i < SLI_RSRC_MAX; i++) { 3729 sli4->config.extent[i].number = 1; 3730 sli4->config.extent[i].n_alloc = 0; 3731 sli4->config.extent[i].base = &base[i]; 3732 } 3733 3734 sli4->config.extent[SLI_RSRC_FCOE_VFI].base[0] = read_config->vfi_base; 3735 sli4->config.extent[SLI_RSRC_FCOE_VFI].size = read_config->vfi_count; 3736 3737 sli4->config.extent[SLI_RSRC_FCOE_VPI].base[0] = read_config->vpi_base; 3738 sli4->config.extent[SLI_RSRC_FCOE_VPI].size = read_config->vpi_count; 3739 3740 sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0] = read_config->rpi_base; 3741 sli4->config.extent[SLI_RSRC_FCOE_RPI].size = read_config->rpi_count; 3742 3743 sli4->config.extent[SLI_RSRC_FCOE_XRI].base[0] = read_config->xri_base; 3744 sli4->config.extent[SLI_RSRC_FCOE_XRI].size = OCS_MIN(255,read_config->xri_count); 3745 3746 sli4->config.extent[SLI_RSRC_FCOE_FCFI].base[0] = 0; 3747 sli4->config.extent[SLI_RSRC_FCOE_FCFI].size = read_config->fcfi_count; 3748 } else { 3749 /* TODO extents*/ 3750 ; 3751 } 3752 3753 for (i = 0; i < SLI_RSRC_MAX; i++) { 3754 total = sli4->config.extent[i].number * sli4->config.extent[i].size; 3755 sli4->config.extent[i].use_map = ocs_bitmap_alloc(total); 3756 if (NULL == sli4->config.extent[i].use_map) { 3757 ocs_log_err(sli4->os, "bitmap memory allocation failed " 3758 "resource %d\n", i); 3759 return -1; 3760 } 3761 sli4->config.extent[i].map_size = total; 3762 } 3763 3764 sli4->config.topology = read_config->topology; 3765 sli4->config.ptv = read_config->ptv; 3766 if (sli4->config.ptv){ 3767 sli4->config.tf = read_config->tf; 3768 sli4->config.pt = read_config->pt; 3769 } 3770 ocs_log_info(sli4->os, "Persistent Topology: PTV: %d, TF: %d, PT: %d \n", 3771 sli4->config.topology, sli4->config.ptv, sli4->config.tf, sli4->config.pt); 3772 3773 switch (sli4->config.topology) { 3774 case SLI4_READ_CFG_TOPO_FCOE: 3775 ocs_log_debug(sli4->os, "FCoE\n"); 3776 break; 3777 case SLI4_READ_CFG_TOPO_FC: 3778 ocs_log_debug(sli4->os, "FC (unknown)\n"); 3779 break; 3780 case SLI4_READ_CFG_TOPO_FC_DA: 3781 ocs_log_debug(sli4->os, "FC (direct attach)\n"); 3782 break; 3783 case SLI4_READ_CFG_TOPO_FC_AL: 3784 ocs_log_debug(sli4->os, "FC (arbitrated loop)\n"); 3785 break; 3786 default: 3787 ocs_log_test(sli4->os, "bad topology %#x\n", sli4->config.topology); 3788 } 3789 3790 sli4->config.e_d_tov = read_config->e_d_tov; 3791 sli4->config.r_a_tov = read_config->r_a_tov; 3792 3793 sli4->config.link_module_type = read_config->lmt; 3794 3795 sli4->config.max_qcount[SLI_QTYPE_EQ] = read_config->eq_count; 3796 sli4->config.max_qcount[SLI_QTYPE_CQ] = read_config->cq_count; 3797 sli4->config.max_qcount[SLI_QTYPE_WQ] = read_config->wq_count; 3798 sli4->config.max_qcount[SLI_QTYPE_RQ] = read_config->rq_count; 3799 3800 /* 3801 * READ_CONFIG doesn't give the max number of MQ. Applications 3802 * will typically want 1, but we may need another at some future 3803 * date. Dummy up a "max" MQ count here. 3804 */ 3805 sli4->config.max_qcount[SLI_QTYPE_MQ] = SLI_USER_MQ_COUNT; 3806 } else { 3807 ocs_log_err(sli4->os, "bad READ_CONFIG write\n"); 3808 return -1; 3809 } 3810 3811 if (sli_cmd_common_get_sli4_parameters(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 3812 sli4_res_common_get_sli4_parameters_t *parms = (sli4_res_common_get_sli4_parameters_t *) 3813 (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed)); 3814 3815 if (sli_bmbx_command(sli4)) { 3816 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_SLI4_PARAMETERS)\n"); 3817 return -1; 3818 } else if (parms->hdr.status) { 3819 ocs_log_err(sli4->os, "COMMON_GET_SLI4_PARAMETERS bad status %#x att'l %#x\n", 3820 parms->hdr.status, parms->hdr.additional_status); 3821 return -1; 3822 } 3823 3824 sli4->config.auto_reg = parms->areg; 3825 sli4->config.auto_xfer_rdy = parms->agxf; 3826 sli4->config.hdr_template_req = parms->hdrr; 3827 sli4->config.t10_dif_inline_capable = parms->timm; 3828 sli4->config.t10_dif_separate_capable = parms->tsmm; 3829 3830 sli4->config.mq_create_version = parms->mqv; 3831 sli4->config.cq_create_version = parms->cqv; 3832 sli4->config.rq_min_buf_size = parms->min_rq_buffer_size; 3833 sli4->config.rq_max_buf_size = parms->max_rq_buffer_size; 3834 3835 sli4->config.qpage_count[SLI_QTYPE_EQ] = parms->eq_page_cnt; 3836 sli4->config.qpage_count[SLI_QTYPE_CQ] = parms->cq_page_cnt; 3837 sli4->config.qpage_count[SLI_QTYPE_MQ] = parms->mq_page_cnt; 3838 sli4->config.qpage_count[SLI_QTYPE_WQ] = parms->wq_page_cnt; 3839 sli4->config.qpage_count[SLI_QTYPE_RQ] = parms->rq_page_cnt; 3840 3841 /* save count methods and masks for each queue type */ 3842 sli4->config.count_mask[SLI_QTYPE_EQ] = parms->eqe_count_mask; 3843 sli4->config.count_method[SLI_QTYPE_EQ] = parms->eqe_count_method; 3844 sli4->config.count_mask[SLI_QTYPE_CQ] = parms->cqe_count_mask; 3845 sli4->config.count_method[SLI_QTYPE_CQ] = parms->cqe_count_method; 3846 sli4->config.count_mask[SLI_QTYPE_MQ] = parms->mqe_count_mask; 3847 sli4->config.count_method[SLI_QTYPE_MQ] = parms->mqe_count_method; 3848 sli4->config.count_mask[SLI_QTYPE_WQ] = parms->wqe_count_mask; 3849 sli4->config.count_method[SLI_QTYPE_WQ] = parms->wqe_count_method; 3850 sli4->config.count_mask[SLI_QTYPE_RQ] = parms->rqe_count_mask; 3851 sli4->config.count_method[SLI_QTYPE_RQ] = parms->rqe_count_method; 3852 3853 /* now calculate max queue entries */ 3854 sli_calc_max_qentries(sli4); 3855 3856 sli4->config.max_sgl_pages = parms->sgl_page_cnt; /* max # of pages */ 3857 sli4->config.sgl_page_sizes = parms->sgl_page_sizes; /* bit map of available sizes */ 3858 /* ignore HLM here. Use value from REQUEST_FEATURES */ 3859 3860 sli4->config.sge_supported_length = parms->sge_supported_length; 3861 if (sli4->config.sge_supported_length > OCS_MAX_SGE_SIZE) 3862 sli4->config.sge_supported_length = OCS_MAX_SGE_SIZE; 3863 3864 sli4->config.sgl_pre_registration_required = parms->sglr; 3865 /* default to using pre-registered SGL's */ 3866 sli4->config.sgl_pre_registered = TRUE; 3867 3868 sli4->config.perf_hint = parms->phon; 3869 sli4->config.perf_wq_id_association = parms->phwq; 3870 3871 sli4->config.rq_batch = parms->rq_db_window; 3872 3873 /* save the fields for skyhawk SGL chaining */ 3874 sli4->config.sgl_chaining_params.chaining_capable = 3875 (parms->sglc == 1); 3876 sli4->config.sgl_chaining_params.frag_num_field_offset = 3877 parms->frag_num_field_offset; 3878 sli4->config.sgl_chaining_params.frag_num_field_mask = 3879 (1ull << parms->frag_num_field_size) - 1; 3880 sli4->config.sgl_chaining_params.sgl_index_field_offset = 3881 parms->sgl_index_field_offset; 3882 sli4->config.sgl_chaining_params.sgl_index_field_mask = 3883 (1ull << parms->sgl_index_field_size) - 1; 3884 sli4->config.sgl_chaining_params.chain_sge_initial_value_lo = 3885 parms->chain_sge_initial_value_lo; 3886 sli4->config.sgl_chaining_params.chain_sge_initial_value_hi = 3887 parms->chain_sge_initial_value_hi; 3888 3889 /* Use the highest available WQE size. */ 3890 if (parms->wqe_sizes & SLI4_128BYTE_WQE_SUPPORT) { 3891 sli4->config.wqe_size = SLI4_WQE_EXT_BYTES; 3892 } else { 3893 sli4->config.wqe_size = SLI4_WQE_BYTES; 3894 } 3895 } 3896 3897 if (sli_query_fw_config(sli4)) { 3898 ocs_log_err(sli4->os, "Error sending QUERY_FW_CONFIG\n"); 3899 return -1; 3900 } 3901 3902 sli4->config.port_number = 0; 3903 3904 /* 3905 * Issue COMMON_GET_CNTL_ATTRIBUTES to get port_number. Temporarily 3906 * uses VPD DMA buffer as the response won't fit in the embedded 3907 * buffer. 3908 */ 3909 if (sli_cmd_common_get_cntl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) { 3910 sli4_res_common_get_cntl_attributes_t *attr = sli4->vpd.data.virt; 3911 3912 if (sli_bmbx_command(sli4)) { 3913 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_CNTL_ATTRIBUTES)\n"); 3914 return -1; 3915 } else if (attr->hdr.status) { 3916 ocs_log_err(sli4->os, "COMMON_GET_CNTL_ATTRIBUTES bad status %#x att'l %#x\n", 3917 attr->hdr.status, attr->hdr.additional_status); 3918 return -1; 3919 } 3920 3921 sli4->config.port_number = attr->port_number; 3922 3923 ocs_memcpy(sli4->config.bios_version_string, attr->bios_version_string, 3924 sizeof(sli4->config.bios_version_string)); 3925 } else { 3926 ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ATTRIBUTES write\n"); 3927 return -1; 3928 } 3929 3930 if (ocs_dma_alloc(sli4->os, &get_cntl_addl_data, sizeof(sli4_res_common_get_cntl_addl_attributes_t), 3931 OCS_MIN_DMA_ALIGNMENT)) { 3932 ocs_log_err(sli4->os, "Failed to allocate memory for GET_CNTL_ADDL_ATTR data\n"); 3933 } else { 3934 if (sli_cmd_common_get_cntl_addl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 3935 &get_cntl_addl_data)) { 3936 sli4_res_common_get_cntl_addl_attributes_t *attr = get_cntl_addl_data.virt; 3937 3938 if (sli_bmbx_command(sli4)) { 3939 ocs_log_crit(sli4->os, 3940 "bootstrap mailbox write fail (COMMON_GET_CNTL_ADDL_ATTRIBUTES)\n"); 3941 ocs_dma_free(sli4->os, &get_cntl_addl_data); 3942 return -1; 3943 } 3944 if (attr->hdr.status) { 3945 ocs_log_err(sli4->os, "COMMON_GET_CNTL_ADDL_ATTRIBUTES bad status %#x\n", 3946 attr->hdr.status); 3947 ocs_dma_free(sli4->os, &get_cntl_addl_data); 3948 return -1; 3949 } 3950 3951 ocs_memcpy(sli4->config.ipl_name, attr->ipl_file_name, sizeof(sli4->config.ipl_name)); 3952 3953 ocs_log_debug(sli4->os, "IPL:%s \n", (char*)sli4->config.ipl_name); 3954 } else { 3955 ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ADDL_ATTRIBUTES write\n"); 3956 ocs_dma_free(sli4->os, &get_cntl_addl_data); 3957 return -1; 3958 } 3959 3960 ocs_dma_free(sli4->os, &get_cntl_addl_data); 3961 } 3962 3963 if (sli_cmd_common_get_port_name(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 3964 sli4_res_common_get_port_name_t *port_name = (sli4_res_common_get_port_name_t *)(((uint8_t *)sli4->bmbx.virt) + 3965 offsetof(sli4_cmd_sli_config_t, payload.embed)); 3966 3967 if (sli_bmbx_command(sli4)) { 3968 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_PORT_NAME)\n"); 3969 return -1; 3970 } 3971 3972 sli4->config.port_name[0] = port_name->port_name[sli4->config.port_number]; 3973 } 3974 sli4->config.port_name[1] = '\0'; 3975 3976 if (sli_cmd_read_rev(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) { 3977 sli4_cmd_read_rev_t *read_rev = sli4->bmbx.virt; 3978 3979 if (sli_bmbx_command(sli4)) { 3980 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_REV)\n"); 3981 return -1; 3982 } 3983 if (read_rev->hdr.status) { 3984 ocs_log_err(sli4->os, "READ_REV bad status %#x\n", 3985 read_rev->hdr.status); 3986 return -1; 3987 } 3988 3989 sli4->config.fw_rev[0] = read_rev->first_fw_id; 3990 ocs_memcpy(sli4->config.fw_name[0],read_rev->first_fw_name, sizeof(sli4->config.fw_name[0])); 3991 3992 sli4->config.fw_rev[1] = read_rev->second_fw_id; 3993 ocs_memcpy(sli4->config.fw_name[1],read_rev->second_fw_name, sizeof(sli4->config.fw_name[1])); 3994 3995 sli4->config.hw_rev[0] = read_rev->first_hw_revision; 3996 sli4->config.hw_rev[1] = read_rev->second_hw_revision; 3997 sli4->config.hw_rev[2] = read_rev->third_hw_revision; 3998 3999 ocs_log_debug(sli4->os, "FW1:%s (%08x) / FW2:%s (%08x)\n", 4000 read_rev->first_fw_name, read_rev->first_fw_id, 4001 read_rev->second_fw_name, read_rev->second_fw_id); 4002 4003 ocs_log_debug(sli4->os, "HW1: %08x / HW2: %08x\n", read_rev->first_hw_revision, 4004 read_rev->second_hw_revision); 4005 4006 /* Check that all VPD data was returned */ 4007 if (read_rev->returned_vpd_length != read_rev->actual_vpd_length) { 4008 ocs_log_test(sli4->os, "VPD length: available=%d returned=%d actual=%d\n", 4009 read_rev->available_length, 4010 read_rev->returned_vpd_length, 4011 read_rev->actual_vpd_length); 4012 } 4013 sli4->vpd.length = read_rev->returned_vpd_length; 4014 } else { 4015 ocs_log_err(sli4->os, "bad READ_REV write\n"); 4016 return -1; 4017 } 4018 4019 if (sli_cmd_read_nvparms(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) { 4020 sli4_cmd_read_nvparms_t *read_nvparms = sli4->bmbx.virt; 4021 4022 if (sli_bmbx_command(sli4)) { 4023 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_NVPARMS)\n"); 4024 return -1; 4025 } 4026 if (read_nvparms->hdr.status) { 4027 ocs_log_err(sli4->os, "READ_NVPARMS bad status %#x\n", 4028 read_nvparms->hdr.status); 4029 return -1; 4030 } 4031 4032 ocs_memcpy(sli4->config.wwpn, read_nvparms->wwpn, sizeof(sli4->config.wwpn)); 4033 ocs_memcpy(sli4->config.wwnn, read_nvparms->wwnn, sizeof(sli4->config.wwnn)); 4034 4035 ocs_log_debug(sli4->os, "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 4036 sli4->config.wwpn[0], 4037 sli4->config.wwpn[1], 4038 sli4->config.wwpn[2], 4039 sli4->config.wwpn[3], 4040 sli4->config.wwpn[4], 4041 sli4->config.wwpn[5], 4042 sli4->config.wwpn[6], 4043 sli4->config.wwpn[7]); 4044 ocs_log_debug(sli4->os, "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 4045 sli4->config.wwnn[0], 4046 sli4->config.wwnn[1], 4047 sli4->config.wwnn[2], 4048 sli4->config.wwnn[3], 4049 sli4->config.wwnn[4], 4050 sli4->config.wwnn[5], 4051 sli4->config.wwnn[6], 4052 sli4->config.wwnn[7]); 4053 } else { 4054 ocs_log_err(sli4->os, "bad READ_NVPARMS write\n"); 4055 return -1; 4056 } 4057 4058 return 0; 4059 } 4060 4061 /**************************************************************************** 4062 * Public functions 4063 */ 4064 4065 /** 4066 * @ingroup sli 4067 * @brief Set up the SLI context. 4068 * 4069 * @param sli4 SLI context. 4070 * @param os Device abstraction. 4071 * @param port_type Protocol type of port (for example, FC and NIC). 4072 * 4073 * @return Returns 0 on success, or a non-zero value on failure. 4074 */ 4075 int32_t 4076 sli_setup(sli4_t *sli4, ocs_os_handle_t os, sli4_port_type_e port_type) 4077 { 4078 uint32_t sli_intf = UINT32_MAX; 4079 uint32_t pci_class_rev = 0; 4080 uint32_t rev_id = 0; 4081 uint32_t family = 0; 4082 uint32_t i; 4083 sli4_asic_entry_t *asic; 4084 4085 ocs_memset(sli4, 0, sizeof(sli4_t)); 4086 4087 sli4->os = os; 4088 sli4->port_type = port_type; 4089 4090 /* 4091 * Read the SLI_INTF register to discover the register layout 4092 * and other capability information 4093 */ 4094 sli_intf = ocs_config_read32(os, SLI4_INTF_REG); 4095 4096 if (sli_intf_valid_check(sli_intf)) { 4097 ocs_log_err(os, "SLI_INTF is not valid\n"); 4098 return -1; 4099 } 4100 4101 /* driver only support SLI-4 */ 4102 sli4->sli_rev = sli_intf_sli_revision(sli_intf); 4103 if (4 != sli4->sli_rev) { 4104 ocs_log_err(os, "Unsupported SLI revision (intf=%#x)\n", 4105 sli_intf); 4106 return -1; 4107 } 4108 4109 sli4->sli_family = sli_intf_sli_family(sli_intf); 4110 4111 sli4->if_type = sli_intf_if_type(sli_intf); 4112 4113 if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type) || 4114 (SLI4_IF_TYPE_LANCER_G7 == sli4->if_type)) { 4115 ocs_log_debug(os, "status=%#x error1=%#x error2=%#x\n", 4116 sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS), 4117 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1), 4118 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2)); 4119 } 4120 4121 /* 4122 * set the ASIC type and revision 4123 */ 4124 pci_class_rev = ocs_config_read32(os, SLI4_PCI_CLASS_REVISION); 4125 rev_id = sli_pci_rev_id(pci_class_rev); 4126 family = sli4->sli_family; 4127 if (family == SLI4_FAMILY_CHECK_ASIC_TYPE) { 4128 uint32_t asic_id = ocs_config_read32(os, SLI4_ASIC_ID_REG); 4129 family = sli_asic_gen(asic_id); 4130 } 4131 4132 for (i = 0, asic = sli4_asic_table; i < ARRAY_SIZE(sli4_asic_table); i++, asic++) { 4133 if ((rev_id == asic->rev_id) && (family == asic->family)) { 4134 sli4->asic_type = asic->type; 4135 sli4->asic_rev = asic->rev; 4136 break; 4137 } 4138 } 4139 /* Fail if no matching asic type/rev was found */ 4140 if( (sli4->asic_type == 0) || (sli4->asic_rev == 0)) { 4141 ocs_log_err(os, "no matching asic family/rev found: %02x/%02x\n", family, rev_id); 4142 return -1; 4143 } 4144 4145 /* 4146 * The bootstrap mailbox is equivalent to a MQ with a single 256 byte 4147 * entry, a CQ with a single 16 byte entry, and no event queue. 4148 * Alignment must be 16 bytes as the low order address bits in the 4149 * address register are also control / status. 4150 */ 4151 if (ocs_dma_alloc(sli4->os, &sli4->bmbx, SLI4_BMBX_SIZE + 4152 sizeof(sli4_mcqe_t), 16)) { 4153 ocs_log_err(os, "bootstrap mailbox allocation failed\n"); 4154 return -1; 4155 } 4156 4157 if (sli4->bmbx.phys & SLI4_BMBX_MASK_LO) { 4158 ocs_log_err(os, "bad alignment for bootstrap mailbox\n"); 4159 return -1; 4160 } 4161 4162 ocs_log_debug(os, "bmbx v=%p p=0x%x %08x s=%zd\n", sli4->bmbx.virt, 4163 ocs_addr32_hi(sli4->bmbx.phys), 4164 ocs_addr32_lo(sli4->bmbx.phys), 4165 sli4->bmbx.size); 4166 4167 /* TODO 4096 is arbitrary. What should this value actually be? */ 4168 if (ocs_dma_alloc(sli4->os, &sli4->vpd.data, 4096/*TODO*/, 4096)) { 4169 /* Note that failure isn't fatal in this specific case */ 4170 sli4->vpd.data.size = 0; 4171 ocs_log_test(os, "VPD buffer allocation failed\n"); 4172 } 4173 4174 if (sli_fw_init(sli4)) { 4175 ocs_log_err(sli4->os, "FW initialization failed\n"); 4176 return -1; 4177 } 4178 4179 /* 4180 * Set one of fcpi(initiator), fcpt(target), fcpc(combined) to true 4181 * in addition to any other desired features 4182 */ 4183 sli4->config.features.flag.iaab = TRUE; 4184 sli4->config.features.flag.npiv = TRUE; 4185 sli4->config.features.flag.dif = TRUE; 4186 sli4->config.features.flag.vf = TRUE; 4187 sli4->config.features.flag.fcpc = TRUE; 4188 sli4->config.features.flag.iaar = TRUE; 4189 sli4->config.features.flag.hlm = TRUE; 4190 sli4->config.features.flag.perfh = TRUE; 4191 sli4->config.features.flag.rxseq = TRUE; 4192 sli4->config.features.flag.rxri = TRUE; 4193 sli4->config.features.flag.mrqp = TRUE; 4194 4195 /* use performance hints if available */ 4196 if (sli4->config.perf_hint) { 4197 sli4->config.features.flag.perfh = TRUE; 4198 } 4199 4200 if (sli_request_features(sli4, &sli4->config.features, TRUE)) { 4201 return -1; 4202 } 4203 4204 if (sli_get_config(sli4)) { 4205 return -1; 4206 } 4207 4208 return 0; 4209 } 4210 4211 bool 4212 sli_persist_topology_enabled(sli4_t *sli4) 4213 { 4214 return (sli4->config.ptv); 4215 } 4216 4217 int32_t 4218 sli_init(sli4_t *sli4) 4219 { 4220 4221 if (sli4->config.has_extents) { 4222 /* TODO COMMON_ALLOC_RESOURCE_EXTENTS */; 4223 ocs_log_test(sli4->os, "XXX need to implement extent allocation\n"); 4224 return -1; 4225 } 4226 4227 sli4->config.features.flag.hlm = sli4->config.high_login_mode; 4228 sli4->config.features.flag.rxseq = FALSE; 4229 sli4->config.features.flag.rxri = FALSE; 4230 4231 if (sli_request_features(sli4, &sli4->config.features, FALSE)) { 4232 return -1; 4233 } 4234 4235 return 0; 4236 } 4237 4238 int32_t 4239 sli_reset(sli4_t *sli4) 4240 { 4241 uint32_t i; 4242 4243 if (sli_fw_init(sli4)) { 4244 ocs_log_crit(sli4->os, "FW initialization failed\n"); 4245 return -1; 4246 } 4247 4248 if (sli4->config.extent[0].base) { 4249 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t)); 4250 sli4->config.extent[0].base = NULL; 4251 } 4252 4253 for (i = 0; i < SLI_RSRC_MAX; i++) { 4254 if (sli4->config.extent[i].use_map) { 4255 ocs_bitmap_free(sli4->config.extent[i].use_map); 4256 sli4->config.extent[i].use_map = NULL; 4257 } 4258 sli4->config.extent[i].base = NULL; 4259 } 4260 4261 if (sli_get_config(sli4)) { 4262 return -1; 4263 } 4264 4265 return 0; 4266 } 4267 4268 /** 4269 * @ingroup sli 4270 * @brief Issue a Firmware Reset. 4271 * 4272 * @par Description 4273 * Issues a Firmware Reset to the chip. This reset affects the entire chip, 4274 * so all PCI function on the same PCI bus and device are affected. 4275 * @n @n This type of reset can be used to activate newly downloaded firmware. 4276 * @n @n The driver should be considered to be in an unknown state after this 4277 * reset and should be reloaded. 4278 * 4279 * @param sli4 SLI context. 4280 * 4281 * @return Returns 0 on success, or -1 otherwise. 4282 */ 4283 4284 int32_t 4285 sli_fw_reset(sli4_t *sli4) 4286 { 4287 uint32_t val; 4288 uint32_t ready; 4289 4290 /* 4291 * Firmware must be ready before issuing the reset. 4292 */ 4293 ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC); 4294 if (!ready) { 4295 ocs_log_crit(sli4->os, "FW status is NOT ready\n"); 4296 return -1; 4297 } 4298 switch(sli4->if_type) { 4299 case SLI4_IF_TYPE_BE3_SKH_PF: 4300 /* BE3 / Skyhawk use PCICFG_SOFT_RESET_CSR */ 4301 val = ocs_config_read32(sli4->os, SLI4_PCI_SOFT_RESET_CSR); 4302 val |= SLI4_PCI_SOFT_RESET_MASK; 4303 ocs_config_write32(sli4->os, SLI4_PCI_SOFT_RESET_CSR, val); 4304 break; 4305 case SLI4_IF_TYPE_LANCER_FC_ETH: 4306 /* Lancer uses PHYDEV_CONTROL */ 4307 4308 val = SLI4_PHYDEV_CONTROL_FRST; 4309 sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, val); 4310 break; 4311 default: 4312 ocs_log_test(sli4->os, "Unexpected iftype %d\n", sli4->if_type); 4313 return -1; 4314 break; 4315 } 4316 4317 /* wait for the FW to become ready after the reset */ 4318 ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC); 4319 if (!ready) { 4320 ocs_log_crit(sli4->os, "Failed to become ready after firmware reset\n"); 4321 return -1; 4322 } 4323 return 0; 4324 } 4325 4326 /** 4327 * @ingroup sli 4328 * @brief Tear down a SLI context. 4329 * 4330 * @param sli4 SLI context. 4331 * 4332 * @return Returns 0 on success, or non-zero otherwise. 4333 */ 4334 int32_t 4335 sli_teardown(sli4_t *sli4) 4336 { 4337 uint32_t i; 4338 4339 if (sli4->config.extent[0].base) { 4340 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t)); 4341 sli4->config.extent[0].base = NULL; 4342 } 4343 4344 for (i = 0; i < SLI_RSRC_MAX; i++) { 4345 if (sli4->config.has_extents) { 4346 /* TODO COMMON_DEALLOC_RESOURCE_EXTENTS */; 4347 } 4348 4349 sli4->config.extent[i].base = NULL; 4350 4351 ocs_bitmap_free(sli4->config.extent[i].use_map); 4352 sli4->config.extent[i].use_map = NULL; 4353 } 4354 4355 if (sli_fw_term(sli4)) { 4356 ocs_log_err(sli4->os, "FW deinitialization failed\n"); 4357 } 4358 4359 ocs_dma_free(sli4->os, &sli4->vpd.data); 4360 ocs_dma_free(sli4->os, &sli4->bmbx); 4361 4362 return 0; 4363 } 4364 4365 /** 4366 * @ingroup sli 4367 * @brief Register a callback for the given event. 4368 * 4369 * @param sli4 SLI context. 4370 * @param which Event of interest. 4371 * @param func Function to call when the event occurs. 4372 * @param arg Argument passed to the callback function. 4373 * 4374 * @return Returns 0 on success, or non-zero otherwise. 4375 */ 4376 int32_t 4377 sli_callback(sli4_t *sli4, sli4_callback_e which, void *func, void *arg) 4378 { 4379 4380 if (!sli4 || !func || (which >= SLI4_CB_MAX)) { 4381 ocs_log_err(NULL, "bad parameter sli4=%p which=%#x func=%p\n", 4382 sli4, which, func); 4383 return -1; 4384 } 4385 4386 switch (which) { 4387 case SLI4_CB_LINK: 4388 sli4->link = func; 4389 sli4->link_arg = arg; 4390 break; 4391 case SLI4_CB_FIP: 4392 sli4->fip = func; 4393 sli4->fip_arg = arg; 4394 break; 4395 default: 4396 ocs_log_test(sli4->os, "unknown callback %#x\n", which); 4397 return -1; 4398 } 4399 4400 return 0; 4401 } 4402 4403 /** 4404 * @ingroup sli 4405 * @brief Initialize a queue object. 4406 * 4407 * @par Description 4408 * This initializes the sli4_queue_t object members, including the underlying 4409 * DMA memory. 4410 * 4411 * @param sli4 SLI context. 4412 * @param q Pointer to queue object. 4413 * @param qtype Type of queue to create. 4414 * @param size Size of each entry. 4415 * @param n_entries Number of entries to allocate. 4416 * @param align Starting memory address alignment. 4417 * 4418 * @note Checks if using the existing DMA memory (if any) is possible. If not, 4419 * it frees the existing memory and re-allocates. 4420 * 4421 * @return Returns 0 on success, or non-zero otherwise. 4422 */ 4423 int32_t 4424 __sli_queue_init(sli4_t *sli4, sli4_queue_t *q, uint32_t qtype, 4425 size_t size, uint32_t n_entries, uint32_t align) 4426 { 4427 4428 if ((q->dma.virt == NULL) || (size != q->size) || (n_entries != q->length)) { 4429 if (q->dma.size) { 4430 ocs_dma_free(sli4->os, &q->dma); 4431 } 4432 4433 ocs_memset(q, 0, sizeof(sli4_queue_t)); 4434 4435 if (ocs_dma_alloc(sli4->os, &q->dma, size * n_entries, align)) { 4436 ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]); 4437 return -1; 4438 } 4439 4440 ocs_memset(q->dma.virt, 0, size * n_entries); 4441 4442 ocs_lock_init(sli4->os, &q->lock, "%s lock[%d:%p]", 4443 SLI_QNAME[qtype], ocs_instance(sli4->os), &q->lock); 4444 4445 q->type = qtype; 4446 q->size = size; 4447 q->length = n_entries; 4448 4449 /* Limit to hwf the queue size per interrupt */ 4450 q->proc_limit = n_entries / 2; 4451 4452 if ( (q->type == SLI_QTYPE_EQ) || (q->type == SLI_QTYPE_CQ) ) { 4453 /* For prism, phase will be flipped after a sweep through eq and cq */ 4454 q->phase = 1; 4455 } 4456 4457 switch(q->type) { 4458 case SLI_QTYPE_EQ: 4459 q->posted_limit = q->length / 2; 4460 break; 4461 default: 4462 if ((sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) || 4463 (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF)) { 4464 /* For Skyhawk, ring the doorbell more often */ 4465 q->posted_limit = 8; 4466 } else { 4467 q->posted_limit = 64; 4468 } 4469 break; 4470 } 4471 } 4472 4473 return 0; 4474 } 4475 4476 /** 4477 * @ingroup sli 4478 * @brief Issue the command to create a queue. 4479 * 4480 * @param sli4 SLI context. 4481 * @param q Pointer to queue object. 4482 * 4483 * @return Returns 0 on success, or non-zero otherwise. 4484 */ 4485 int32_t 4486 __sli_create_queue(sli4_t *sli4, sli4_queue_t *q) 4487 { 4488 sli4_res_common_create_queue_t *res_q = NULL; 4489 4490 if (sli_bmbx_command(sli4)){ 4491 ocs_log_crit(sli4->os, "bootstrap mailbox write fail %s\n", 4492 SLI_QNAME[q->type]); 4493 ocs_dma_free(sli4->os, &q->dma); 4494 return -1; 4495 } 4496 if (sli_res_sli_config(sli4->bmbx.virt)) { 4497 ocs_log_err(sli4->os, "bad status create %s\n", SLI_QNAME[q->type]); 4498 ocs_dma_free(sli4->os, &q->dma); 4499 return -1; 4500 } 4501 res_q = (void *)((uint8_t *)sli4->bmbx.virt + 4502 offsetof(sli4_cmd_sli_config_t, payload)); 4503 4504 if (res_q->hdr.status) { 4505 ocs_log_err(sli4->os, "bad create %s status=%#x addl=%#x\n", 4506 SLI_QNAME[q->type], 4507 res_q->hdr.status, res_q->hdr.additional_status); 4508 ocs_dma_free(sli4->os, &q->dma); 4509 return -1; 4510 } else { 4511 q->id = res_q->q_id; 4512 q->doorbell_offset = res_q->db_offset; 4513 q->doorbell_rset = res_q->db_rs; 4514 4515 switch (q->type) { 4516 case SLI_QTYPE_EQ: 4517 /* No doorbell information in response for EQs */ 4518 q->doorbell_offset = regmap[SLI4_REG_EQ_DOORBELL][sli4->if_type].off; 4519 q->doorbell_rset = regmap[SLI4_REG_EQ_DOORBELL][sli4->if_type].rset; 4520 break; 4521 case SLI_QTYPE_CQ: 4522 /* No doorbell information in response for CQs */ 4523 q->doorbell_offset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].off; 4524 q->doorbell_rset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].rset; 4525 break; 4526 case SLI_QTYPE_MQ: 4527 /* No doorbell information in response for MQs */ 4528 q->doorbell_offset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].off; 4529 q->doorbell_rset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].rset; 4530 break; 4531 case SLI_QTYPE_RQ: 4532 /* set the doorbell for non-skyhawks */ 4533 if (!sli4->config.dual_ulp_capable) { 4534 q->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off; 4535 q->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset; 4536 } 4537 break; 4538 case SLI_QTYPE_WQ: 4539 /* set the doorbell for non-skyhawks */ 4540 if (!sli4->config.dual_ulp_capable) { 4541 q->doorbell_offset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].off; 4542 q->doorbell_rset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].rset; 4543 } 4544 break; 4545 default: 4546 break; 4547 } 4548 } 4549 4550 return 0; 4551 } 4552 4553 /** 4554 * @ingroup sli 4555 * @brief Get queue entry size. 4556 * 4557 * Get queue entry size given queue type. 4558 * 4559 * @param sli4 SLI context 4560 * @param qtype Type for which the entry size is returned. 4561 * 4562 * @return Returns > 0 on success (queue entry size), or a negative value on failure. 4563 */ 4564 int32_t 4565 sli_get_queue_entry_size(sli4_t *sli4, uint32_t qtype) 4566 { 4567 uint32_t size = 0; 4568 4569 if (!sli4) { 4570 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4); 4571 return -1; 4572 } 4573 4574 switch (qtype) { 4575 case SLI_QTYPE_EQ: 4576 size = sizeof(uint32_t); 4577 break; 4578 case SLI_QTYPE_CQ: 4579 size = 16; 4580 break; 4581 case SLI_QTYPE_MQ: 4582 size = 256; 4583 break; 4584 case SLI_QTYPE_WQ: 4585 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 4586 size = sli4->config.wqe_size; 4587 } else { 4588 /* TODO */ 4589 ocs_log_test(sli4->os, "unsupported queue entry size\n"); 4590 return -1; 4591 } 4592 break; 4593 case SLI_QTYPE_RQ: 4594 size = SLI4_FCOE_RQE_SIZE; 4595 break; 4596 default: 4597 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype); 4598 return -1; 4599 } 4600 return size; 4601 } 4602 4603 /** 4604 * @ingroup sli 4605 * @brief Modify the delay timer for all the EQs 4606 * 4607 * @param sli4 SLI context. 4608 * @param eq Array of EQs. 4609 * @param num_eq Count of EQs. 4610 * @param shift Phase shift for staggering interrupts. 4611 * @param delay_mult Delay multiplier for limiting interrupt frequency. 4612 * 4613 * @return Returns 0 on success, or -1 otherwise. 4614 */ 4615 int32_t 4616 sli_eq_modify_delay(sli4_t *sli4, sli4_queue_t *eq, uint32_t num_eq, uint32_t shift, uint32_t delay_mult) 4617 { 4618 4619 sli_cmd_common_modify_eq_delay(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, eq, num_eq, shift, delay_mult); 4620 4621 if (sli_bmbx_command(sli4)) { 4622 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (MODIFY EQ DELAY)\n"); 4623 return -1; 4624 } 4625 if (sli_res_sli_config(sli4->bmbx.virt)) { 4626 ocs_log_err(sli4->os, "bad status MODIFY EQ DELAY\n"); 4627 return -1; 4628 } 4629 4630 return 0; 4631 } 4632 4633 /** 4634 * @ingroup sli 4635 * @brief Allocate a queue. 4636 * 4637 * @par Description 4638 * Allocates DMA memory and configures the requested queue type. 4639 * 4640 * @param sli4 SLI context. 4641 * @param qtype Type of queue to create. 4642 * @param q Pointer to the queue object. 4643 * @param n_entries Number of entries to allocate. 4644 * @param assoc Associated queue (that is, the EQ for a CQ, the CQ for a MQ, and so on). 4645 * @param ulp The ULP to bind, which is only used for WQ and RQs 4646 * 4647 * @return Returns 0 on success, or -1 otherwise. 4648 */ 4649 int32_t 4650 sli_queue_alloc(sli4_t *sli4, uint32_t qtype, sli4_queue_t *q, uint32_t n_entries, 4651 sli4_queue_t *assoc, uint16_t ulp) 4652 { 4653 int32_t size; 4654 uint32_t align = 0; 4655 sli4_create_q_fn_t create = NULL; 4656 4657 if (!sli4 || !q) { 4658 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q); 4659 return -1; 4660 } 4661 4662 /* get queue size */ 4663 size = sli_get_queue_entry_size(sli4, qtype); 4664 if (size < 0) 4665 return -1; 4666 align = SLI_PAGE_SIZE; 4667 4668 switch (qtype) { 4669 case SLI_QTYPE_EQ: 4670 create = sli_cmd_common_create_eq; 4671 break; 4672 case SLI_QTYPE_CQ: 4673 create = sli_cmd_common_create_cq; 4674 break; 4675 case SLI_QTYPE_MQ: 4676 /* Validate the number of entries */ 4677 switch (n_entries) { 4678 case 16: 4679 case 32: 4680 case 64: 4681 case 128: 4682 break; 4683 default: 4684 ocs_log_test(sli4->os, "illegal n_entries value %d for MQ\n", n_entries); 4685 return -1; 4686 } 4687 assoc->u.flag.is_mq = TRUE; 4688 create = sli_cmd_common_create_mq_ext; 4689 break; 4690 case SLI_QTYPE_WQ: 4691 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 4692 if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) { 4693 create = sli_cmd_fcoe_wq_create; 4694 } else { 4695 create = sli_cmd_fcoe_wq_create_v1; 4696 } 4697 } else { 4698 /* TODO */ 4699 ocs_log_test(sli4->os, "unsupported WQ create\n"); 4700 return -1; 4701 } 4702 break; 4703 default: 4704 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype); 4705 return -1; 4706 } 4707 4708 if (__sli_queue_init(sli4, q, qtype, size, n_entries, align)) { 4709 ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]); 4710 return -1; 4711 } 4712 4713 if (create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma, assoc ? assoc->id : 0, ulp)) { 4714 if (__sli_create_queue(sli4, q)) { 4715 ocs_log_err(sli4->os, "create %s failed\n", SLI_QNAME[qtype]); 4716 return -1; 4717 } 4718 q->ulp = ulp; 4719 } else { 4720 ocs_log_err(sli4->os, "cannot create %s\n", SLI_QNAME[qtype]); 4721 return -1; 4722 } 4723 4724 return 0; 4725 } 4726 4727 /** 4728 * @ingroup sli 4729 * @brief Allocate a c queue set. 4730 * 4731 * @param sli4 SLI context. 4732 * @param num_cqs to create 4733 * @param qs Pointers to the queue objects. 4734 * @param n_entries Number of entries to allocate per CQ. 4735 * @param eqs Associated event queues 4736 * 4737 * @return Returns 0 on success, or -1 otherwise. 4738 */ 4739 int32_t 4740 sli_cq_alloc_set(sli4_t *sli4, sli4_queue_t *qs[], uint32_t num_cqs, 4741 uint32_t n_entries, sli4_queue_t *eqs[]) 4742 { 4743 uint32_t i, offset = 0, page_bytes = 0, payload_size, cmd_size = 0; 4744 uint32_t p = 0, page_size = 0, n_cqe = 0, num_pages_cq; 4745 uintptr_t addr; 4746 ocs_dma_t dma; 4747 sli4_req_common_create_cq_set_v0_t *req = NULL; 4748 sli4_res_common_create_queue_set_t *res = NULL; 4749 4750 if (!sli4) { 4751 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4); 4752 return -1; 4753 } 4754 4755 memset(&dma, 0, sizeof(dma)); 4756 4757 /* Align the queue DMA memory */ 4758 for (i = 0; i < num_cqs; i++) { 4759 if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_CQ, SLI4_CQE_BYTES, 4760 n_entries, SLI_PAGE_SIZE)) { 4761 ocs_log_err(sli4->os, "Queue init failed.\n"); 4762 goto error; 4763 } 4764 } 4765 4766 n_cqe = qs[0]->dma.size / SLI4_CQE_BYTES; 4767 switch (n_cqe) { 4768 case 256: 4769 case 512: 4770 case 1024: 4771 case 2048: 4772 page_size = 1; 4773 break; 4774 case 4096: 4775 page_size = 2; 4776 break; 4777 default: 4778 return -1; 4779 } 4780 4781 page_bytes = page_size * SLI_PAGE_SIZE; 4782 num_pages_cq = sli_page_count(qs[0]->dma.size, page_bytes); 4783 cmd_size = sizeof(sli4_req_common_create_cq_set_v0_t) + (8 * num_pages_cq * num_cqs); 4784 payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_set_t)); 4785 4786 if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) { 4787 ocs_log_err(sli4->os, "DMA allocation failed\n"); 4788 goto error; 4789 } 4790 ocs_memset(dma.virt, 0, payload_size); 4791 4792 if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 4793 payload_size, &dma) == -1) { 4794 goto error; 4795 } 4796 4797 /* Fill the request structure */ 4798 4799 req = (sli4_req_common_create_cq_set_v0_t *)((uint8_t *)dma.virt); 4800 req->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ_SET; 4801 req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 4802 req->hdr.version = 0; 4803 req->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t); 4804 req->page_size = page_size; 4805 4806 req->num_pages = num_pages_cq; 4807 switch (req->num_pages) { 4808 case 1: 4809 req->cqecnt = SLI4_CQ_CNT_256; 4810 break; 4811 case 2: 4812 req->cqecnt = SLI4_CQ_CNT_512; 4813 break; 4814 case 4: 4815 req->cqecnt = SLI4_CQ_CNT_1024; 4816 break; 4817 case 8: 4818 req->cqecnt = SLI4_CQ_CNT_LARGE; 4819 req->cqe_count = n_cqe; 4820 break; 4821 default: 4822 ocs_log_test(sli4->os, "num_pages %d not valid\n", req->num_pages); 4823 goto error; 4824 } 4825 4826 req->evt = TRUE; 4827 req->valid = TRUE; 4828 req->arm = FALSE; 4829 req->num_cq_req = num_cqs; 4830 4831 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) 4832 req->autovalid = TRUE; 4833 4834 /* Fill page addresses of all the CQs. */ 4835 for (i = 0; i < num_cqs; i++) { 4836 req->eq_id[i] = eqs[i]->id; 4837 for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += page_bytes) { 4838 req->page_physical_address[offset].low = ocs_addr32_lo(addr); 4839 req->page_physical_address[offset].high = ocs_addr32_hi(addr); 4840 offset++; 4841 } 4842 } 4843 4844 if (sli_bmbx_command(sli4)) { 4845 ocs_log_crit(sli4->os, "bootstrap mailbox write fail CQSet\n"); 4846 goto error; 4847 } 4848 4849 res = (void *)((uint8_t *)dma.virt); 4850 if (res->hdr.status) { 4851 ocs_log_err(sli4->os, "bad create CQSet status=%#x addl=%#x\n", 4852 res->hdr.status, res->hdr.additional_status); 4853 goto error; 4854 } else { 4855 /* Check if we got all requested CQs. */ 4856 if (res->num_q_allocated != num_cqs) { 4857 ocs_log_crit(sli4->os, "Requested count CQs doesnt match.\n"); 4858 goto error; 4859 } 4860 4861 /* Fill the resp cq ids. */ 4862 for (i = 0; i < num_cqs; i++) { 4863 qs[i]->id = res->q_id + i; 4864 qs[i]->doorbell_offset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].off; 4865 qs[i]->doorbell_rset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].rset; 4866 } 4867 } 4868 4869 ocs_dma_free(sli4->os, &dma); 4870 4871 return 0; 4872 4873 error: 4874 for (i = 0; i < num_cqs; i++) { 4875 if (qs[i]->dma.size) { 4876 ocs_dma_free(sli4->os, &qs[i]->dma); 4877 } 4878 } 4879 4880 if (dma.size) { 4881 ocs_dma_free(sli4->os, &dma); 4882 } 4883 4884 return -1; 4885 } 4886 4887 /** 4888 * @ingroup sli 4889 * @brief Free a queue. 4890 * 4891 * @par Description 4892 * Frees DMA memory and de-registers the requested queue. 4893 * 4894 * @param sli4 SLI context. 4895 * @param q Pointer to the queue object. 4896 * @param destroy_queues Non-zero if the mailbox commands should be sent to destroy the queues. 4897 * @param free_memory Non-zero if the DMA memory associated with the queue should be freed. 4898 * 4899 * @return Returns 0 on success, or -1 otherwise. 4900 */ 4901 int32_t 4902 sli_queue_free(sli4_t *sli4, sli4_queue_t *q, uint32_t destroy_queues, uint32_t free_memory) 4903 { 4904 sli4_destroy_q_fn_t destroy = NULL; 4905 int32_t rc = -1; 4906 4907 if (!sli4 || !q) { 4908 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q); 4909 return -1; 4910 } 4911 4912 if (destroy_queues) { 4913 switch (q->type) { 4914 case SLI_QTYPE_EQ: 4915 destroy = sli_cmd_common_destroy_eq; 4916 break; 4917 case SLI_QTYPE_CQ: 4918 destroy = sli_cmd_common_destroy_cq; 4919 break; 4920 case SLI_QTYPE_MQ: 4921 destroy = sli_cmd_common_destroy_mq; 4922 break; 4923 case SLI_QTYPE_WQ: 4924 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 4925 destroy = sli_cmd_fcoe_wq_destroy; 4926 } else { 4927 /* TODO */ 4928 ocs_log_test(sli4->os, "unsupported WQ destroy\n"); 4929 return -1; 4930 } 4931 break; 4932 case SLI_QTYPE_RQ: 4933 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 4934 destroy = sli_cmd_fcoe_rq_destroy; 4935 } else { 4936 /* TODO */ 4937 ocs_log_test(sli4->os, "unsupported RQ destroy\n"); 4938 return -1; 4939 } 4940 break; 4941 default: 4942 ocs_log_test(sli4->os, "bad queue type %d\n", 4943 q->type); 4944 return -1; 4945 } 4946 4947 /* 4948 * Destroying queues makes BE3 sad (version 0 interface type). Rely 4949 * on COMMON_FUNCTION_RESET to free host allocated queue resources 4950 * inside the SLI Port. 4951 */ 4952 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) { 4953 destroy = NULL; 4954 } 4955 4956 /* Destroy the queue if the operation is defined */ 4957 if (destroy && destroy(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, q->id)) { 4958 sli4_res_hdr_t *res = NULL; 4959 4960 if (sli_bmbx_command(sli4)){ 4961 ocs_log_crit(sli4->os, "bootstrap mailbox write fail destroy %s\n", 4962 SLI_QNAME[q->type]); 4963 } else if (sli_res_sli_config(sli4->bmbx.virt)) { 4964 ocs_log_err(sli4->os, "bad status destroy %s\n", SLI_QNAME[q->type]); 4965 } else { 4966 res = (void *)((uint8_t *)sli4->bmbx.virt + 4967 offsetof(sli4_cmd_sli_config_t, payload)); 4968 4969 if (res->status) { 4970 ocs_log_err(sli4->os, "bad destroy %s status=%#x addl=%#x\n", 4971 SLI_QNAME[q->type], 4972 res->status, res->additional_status); 4973 } else { 4974 rc = 0; 4975 } 4976 } 4977 } 4978 } 4979 4980 if (free_memory) { 4981 ocs_lock_free(&q->lock); 4982 4983 if (ocs_dma_free(sli4->os, &q->dma)) { 4984 ocs_log_err(sli4->os, "%s queue ID %d free failed\n", 4985 SLI_QNAME[q->type], q->id); 4986 rc = -1; 4987 } 4988 } 4989 4990 return rc; 4991 } 4992 4993 int32_t 4994 sli_queue_reset(sli4_t *sli4, sli4_queue_t *q) 4995 { 4996 4997 ocs_lock(&q->lock); 4998 4999 q->index = 0; 5000 q->n_posted = 0; 5001 5002 if (SLI_QTYPE_MQ == q->type) { 5003 q->u.r_idx = 0; 5004 } 5005 5006 if (q->dma.virt != NULL) { 5007 ocs_memset(q->dma.virt, 0, (q->size * (uint64_t)q->length)); 5008 } 5009 5010 ocs_unlock(&q->lock); 5011 5012 return 0; 5013 } 5014 5015 /** 5016 * @ingroup sli 5017 * @brief Check if the given queue is empty. 5018 * 5019 * @par Description 5020 * If the valid bit of the current entry is unset, the queue is empty. 5021 * 5022 * @param sli4 SLI context. 5023 * @param q Pointer to the queue object. 5024 * 5025 * @return Returns TRUE if empty, or FALSE otherwise. 5026 */ 5027 int32_t 5028 sli_queue_is_empty(sli4_t *sli4, sli4_queue_t *q) 5029 { 5030 int32_t rc = TRUE; 5031 uint8_t *qe = q->dma.virt; 5032 5033 ocs_lock(&q->lock); 5034 5035 ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD); 5036 5037 qe += q->index * q->size; 5038 5039 rc = !sli_queue_entry_is_valid(q, qe, FALSE); 5040 5041 ocs_unlock(&q->lock); 5042 5043 return rc; 5044 } 5045 5046 /** 5047 * @ingroup sli 5048 * @brief Arm an EQ. 5049 * 5050 * @param sli4 SLI context. 5051 * @param q Pointer to queue object. 5052 * @param arm If TRUE, arm the EQ. 5053 * 5054 * @return Returns 0 on success, or non-zero otherwise. 5055 */ 5056 int32_t 5057 sli_queue_eq_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm) 5058 { 5059 uint32_t val = 0; 5060 5061 ocs_lock(&q->lock); 5062 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) 5063 val = sli_iftype6_eq_doorbell(q->n_posted, q->id, arm); 5064 else 5065 val = sli_eq_doorbell(q->n_posted, q->id, arm); 5066 5067 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 5068 q->n_posted = 0; 5069 ocs_unlock(&q->lock); 5070 5071 return 0; 5072 } 5073 5074 /** 5075 * @ingroup sli 5076 * @brief Arm a queue. 5077 * 5078 * @param sli4 SLI context. 5079 * @param q Pointer to queue object. 5080 * @param arm If TRUE, arm the queue. 5081 * 5082 * @return Returns 0 on success, or non-zero otherwise. 5083 */ 5084 int32_t 5085 sli_queue_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm) 5086 { 5087 uint32_t val = 0; 5088 5089 ocs_lock(&q->lock); 5090 5091 switch (q->type) { 5092 case SLI_QTYPE_EQ: 5093 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) 5094 val = sli_iftype6_eq_doorbell(q->n_posted, q->id, arm); 5095 else 5096 val = sli_eq_doorbell(q->n_posted, q->id, arm); 5097 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 5098 q->n_posted = 0; 5099 break; 5100 case SLI_QTYPE_CQ: 5101 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) 5102 val = sli_iftype6_cq_doorbell(q->n_posted, q->id, arm); 5103 else 5104 val = sli_cq_doorbell(q->n_posted, q->id, arm); 5105 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val); 5106 q->n_posted = 0; 5107 break; 5108 default: 5109 ocs_log_test(sli4->os, "should only be used for EQ/CQ, not %s\n", 5110 SLI_QNAME[q->type]); 5111 } 5112 5113 ocs_unlock(&q->lock); 5114 5115 return 0; 5116 } 5117 5118 /** 5119 * @ingroup sli 5120 * @brief Write an entry to the queue object. 5121 * 5122 * Note: Assumes the q->lock will be locked and released by the caller. 5123 * 5124 * @param sli4 SLI context. 5125 * @param q Pointer to the queue object. 5126 * @param entry Pointer to the entry contents. 5127 * 5128 * @return Returns queue index on success, or negative error value otherwise. 5129 */ 5130 int32_t 5131 _sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry) 5132 { 5133 int32_t rc = 0; 5134 uint8_t *qe = q->dma.virt; 5135 uint32_t qindex; 5136 5137 qindex = q->index; 5138 qe += q->index * q->size; 5139 5140 if (entry) { 5141 if ((SLI_QTYPE_WQ == q->type) && sli4->config.perf_wq_id_association) { 5142 sli_set_wq_id_association(entry, q->id); 5143 } 5144 #if defined(OCS_INCLUDE_DEBUG) 5145 switch (q->type) { 5146 case SLI_QTYPE_WQ: { 5147 ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, "wqe", entry, q->size); 5148 break; 5149 } 5150 case SLI_QTYPE_MQ: 5151 /* Note: we don't really need to dump the whole 5152 * 256 bytes, just do 64 */ 5153 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mqe outbound", entry, 64); 5154 break; 5155 5156 default: 5157 break; 5158 } 5159 #endif 5160 ocs_memcpy(qe, entry, q->size); 5161 q->n_posted = 1; 5162 } 5163 5164 ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE); 5165 5166 rc = sli_queue_doorbell(sli4, q); 5167 5168 q->index = (q->index + q->n_posted) & (q->length - 1); 5169 q->n_posted = 0; 5170 5171 if (rc < 0) { 5172 /* failure */ 5173 return rc; 5174 } else if (rc > 0) { 5175 /* failure, but we need to return a negative value on failure */ 5176 return -rc; 5177 } else { 5178 return qindex; 5179 } 5180 } 5181 5182 /** 5183 * @ingroup sli 5184 * @brief Write an entry to the queue object. 5185 * 5186 * Note: Assumes the q->lock will be locked and released by the caller. 5187 * 5188 * @param sli4 SLI context. 5189 * @param q Pointer to the queue object. 5190 * @param entry Pointer to the entry contents. 5191 * 5192 * @return Returns queue index on success, or negative error value otherwise. 5193 */ 5194 int32_t 5195 sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry) 5196 { 5197 int32_t rc; 5198 5199 ocs_lock(&q->lock); 5200 rc = _sli_queue_write(sli4, q, entry); 5201 ocs_unlock(&q->lock); 5202 5203 return rc; 5204 } 5205 5206 /** 5207 * @brief Check if the current queue entry is valid. 5208 * 5209 * @param q Pointer to the queue object. 5210 * @param qe Pointer to the queue entry. 5211 * @param clear Boolean to clear valid bit. 5212 * 5213 * @return Returns TRUE if the entry is valid, or FALSE otherwise. 5214 */ 5215 static uint8_t 5216 sli_queue_entry_is_valid(sli4_queue_t *q, uint8_t *qe, uint8_t clear) 5217 { 5218 uint8_t valid = FALSE; 5219 uint8_t valid_bit_set = 0; 5220 5221 switch (q->type) { 5222 case SLI_QTYPE_EQ: 5223 valid = (((sli4_eqe_t *)qe)->vld == q->phase) ? 1 : 0; 5224 if (valid && clear) { 5225 ((sli4_eqe_t *)qe)->vld = 0; 5226 } 5227 break; 5228 case SLI_QTYPE_CQ: 5229 /* 5230 * For both MCQE and WCQE/RCQE, the valid bit 5231 * is bit 31 of dword 3 (0 based) 5232 */ 5233 valid_bit_set = (qe[15] & 0x80) != 0; 5234 if (valid_bit_set == q->phase) 5235 valid = 1; 5236 5237 if (valid & clear) { 5238 qe[15] &= ~0x80; 5239 } 5240 break; 5241 case SLI_QTYPE_MQ: 5242 valid = q->index != q->u.r_idx; 5243 break; 5244 case SLI_QTYPE_RQ: 5245 valid = TRUE; 5246 clear = FALSE; 5247 break; 5248 default: 5249 ocs_log_test(NULL, "doesn't handle type=%#x\n", q->type); 5250 } 5251 5252 if (clear) { 5253 5254 ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE); 5255 } 5256 5257 return valid; 5258 } 5259 5260 /** 5261 * @ingroup sli 5262 * @brief Read an entry from the queue object. 5263 * 5264 * @param sli4 SLI context. 5265 * @param q Pointer to the queue object. 5266 * @param entry Destination pointer for the queue entry contents. 5267 * 5268 * @return Returns 0 on success, or non-zero otherwise. 5269 */ 5270 int32_t 5271 sli_queue_read(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry) 5272 { 5273 int32_t rc = 0; 5274 uint8_t *qe = q->dma.virt; 5275 uint32_t *qindex = NULL; 5276 5277 uint8_t clear = (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4)) ? FALSE : TRUE; 5278 if (SLI_QTYPE_MQ == q->type) { 5279 qindex = &q->u.r_idx; 5280 } else { 5281 qindex = &q->index; 5282 } 5283 5284 ocs_lock(&q->lock); 5285 5286 ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD); 5287 5288 qe += *qindex * q->size; 5289 5290 if (!sli_queue_entry_is_valid(q, qe, clear)) { 5291 ocs_unlock(&q->lock); 5292 return -1; 5293 } 5294 5295 if (entry) { 5296 ocs_memcpy(entry, qe, q->size); 5297 #if defined(OCS_INCLUDE_DEBUG) 5298 switch(q->type) { 5299 case SLI_QTYPE_CQ: 5300 ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "cq", entry, q->size); 5301 break; 5302 case SLI_QTYPE_MQ: 5303 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mq Compl", entry, 64); 5304 break; 5305 case SLI_QTYPE_EQ: 5306 ocs_dump32(OCS_DEBUG_ENABLE_EQ_DUMP, sli4->os, "eq Compl", entry, q->size); 5307 break; 5308 default: 5309 break; 5310 } 5311 #endif 5312 } 5313 5314 switch (q->type) { 5315 case SLI_QTYPE_EQ: 5316 case SLI_QTYPE_CQ: 5317 case SLI_QTYPE_MQ: 5318 *qindex = (*qindex + 1) & (q->length - 1); 5319 if (SLI_QTYPE_MQ != q->type) { 5320 q->n_posted++; 5321 /* 5322 * For prism, the phase value will be used to check the validity of eq/cq entries. 5323 * The value toggles after a complete sweep through the queue. 5324 */ 5325 if ((SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4)) && (*qindex == 0)) { 5326 q->phase ^= (uint16_t) 0x1; 5327 } 5328 } 5329 break; 5330 default: 5331 /* reads don't update the index */ 5332 break; 5333 } 5334 5335 ocs_unlock(&q->lock); 5336 5337 return rc; 5338 } 5339 5340 int32_t 5341 sli_queue_index(sli4_t *sli4, sli4_queue_t *q) 5342 { 5343 5344 if (q) { 5345 return q->index; 5346 } else { 5347 return -1; 5348 } 5349 } 5350 5351 int32_t 5352 sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry) 5353 { 5354 int32_t rc; 5355 5356 ocs_lock(&q->lock); 5357 rc = _sli_queue_poke(sli4, q, index, entry); 5358 ocs_unlock(&q->lock); 5359 5360 return rc; 5361 } 5362 5363 int32_t 5364 _sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry) 5365 { 5366 int32_t rc = 0; 5367 uint8_t *qe = q->dma.virt; 5368 5369 if (index >= q->length) { 5370 return -1; 5371 } 5372 5373 qe += index * q->size; 5374 5375 if (entry) { 5376 ocs_memcpy(qe, entry, q->size); 5377 } 5378 5379 ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE); 5380 5381 return rc; 5382 } 5383 5384 /** 5385 * @ingroup sli 5386 * @brief Allocate SLI Port resources. 5387 * 5388 * @par Description 5389 * Allocate port-related resources, such as VFI, RPI, XRI, and so on. 5390 * Resources are modeled using extents, regardless of whether the underlying 5391 * device implements resource extents. If the device does not implement 5392 * extents, the SLI layer models this as a single (albeit large) extent. 5393 * 5394 * @param sli4 SLI context. 5395 * @param rtype Resource type (for example, RPI or XRI) 5396 * @param rid Allocated resource ID. 5397 * @param index Index into the bitmap. 5398 * 5399 * @return Returns 0 on success, or a non-zero value on failure. 5400 */ 5401 int32_t 5402 sli_resource_alloc(sli4_t *sli4, sli4_resource_e rtype, uint32_t *rid, uint32_t *index) 5403 { 5404 int32_t rc = 0; 5405 uint32_t size; 5406 uint32_t extent_idx; 5407 uint32_t item_idx; 5408 int status; 5409 5410 *rid = UINT32_MAX; 5411 *index = UINT32_MAX; 5412 5413 switch (rtype) { 5414 case SLI_RSRC_FCOE_VFI: 5415 case SLI_RSRC_FCOE_VPI: 5416 case SLI_RSRC_FCOE_RPI: 5417 case SLI_RSRC_FCOE_XRI: 5418 status = ocs_bitmap_find(sli4->config.extent[rtype].use_map, 5419 sli4->config.extent[rtype].map_size); 5420 if (status < 0) { 5421 ocs_log_err(sli4->os, "out of resource %d (alloc=%d)\n", 5422 rtype, sli4->config.extent[rtype].n_alloc); 5423 rc = -1; 5424 break; 5425 } else { 5426 *index = status; 5427 } 5428 5429 size = sli4->config.extent[rtype].size; 5430 5431 extent_idx = *index / size; 5432 item_idx = *index % size; 5433 5434 *rid = sli4->config.extent[rtype].base[extent_idx] + item_idx; 5435 5436 sli4->config.extent[rtype].n_alloc++; 5437 break; 5438 default: 5439 rc = -1; 5440 } 5441 5442 return rc; 5443 } 5444 5445 /** 5446 * @ingroup sli 5447 * @brief Free the SLI Port resources. 5448 * 5449 * @par Description 5450 * Free port-related resources, such as VFI, RPI, XRI, and so. See discussion of 5451 * "extent" usage in sli_resource_alloc. 5452 * 5453 * @param sli4 SLI context. 5454 * @param rtype Resource type (for example, RPI or XRI). 5455 * @param rid Allocated resource ID. 5456 * 5457 * @return Returns 0 on success, or a non-zero value on failure. 5458 */ 5459 int32_t 5460 sli_resource_free(sli4_t *sli4, sli4_resource_e rtype, uint32_t rid) 5461 { 5462 int32_t rc = -1; 5463 uint32_t x; 5464 uint32_t size, *base; 5465 5466 switch (rtype) { 5467 case SLI_RSRC_FCOE_VFI: 5468 case SLI_RSRC_FCOE_VPI: 5469 case SLI_RSRC_FCOE_RPI: 5470 case SLI_RSRC_FCOE_XRI: 5471 /* 5472 * Figure out which extent contains the resource ID. I.e. find 5473 * the extent such that 5474 * extent->base <= resource ID < extent->base + extent->size 5475 */ 5476 base = sli4->config.extent[rtype].base; 5477 size = sli4->config.extent[rtype].size; 5478 5479 /* 5480 * In the case of FW reset, this may be cleared but the force_free path will 5481 * still attempt to free the resource. Prevent a NULL pointer access. 5482 */ 5483 if (base != NULL) { 5484 for (x = 0; x < sli4->config.extent[rtype].number; x++) { 5485 if ((rid >= base[x]) && (rid < (base[x] + size))) { 5486 rid -= base[x]; 5487 ocs_bitmap_clear(sli4->config.extent[rtype].use_map, 5488 (x * size) + rid); 5489 rc = 0; 5490 break; 5491 } 5492 } 5493 } 5494 break; 5495 default: 5496 ; 5497 } 5498 5499 return rc; 5500 } 5501 5502 int32_t 5503 sli_resource_reset(sli4_t *sli4, sli4_resource_e rtype) 5504 { 5505 int32_t rc = -1; 5506 uint32_t i; 5507 5508 switch (rtype) { 5509 case SLI_RSRC_FCOE_VFI: 5510 case SLI_RSRC_FCOE_VPI: 5511 case SLI_RSRC_FCOE_RPI: 5512 case SLI_RSRC_FCOE_XRI: 5513 for (i = 0; i < sli4->config.extent[rtype].map_size; i++) { 5514 ocs_bitmap_clear(sli4->config.extent[rtype].use_map, i); 5515 } 5516 rc = 0; 5517 break; 5518 default: 5519 ; 5520 } 5521 5522 return rc; 5523 } 5524 5525 /** 5526 * @ingroup sli 5527 * @brief Parse an EQ entry to retrieve the CQ_ID for this event. 5528 * 5529 * @param sli4 SLI context. 5530 * @param buf Pointer to the EQ entry. 5531 * @param cq_id CQ_ID for this entry (only valid on success). 5532 * 5533 * @return 5534 * - 0 if success. 5535 * - < 0 if error. 5536 * - > 0 if firmware detects EQ overflow. 5537 */ 5538 int32_t 5539 sli_eq_parse(sli4_t *sli4, uint8_t *buf, uint16_t *cq_id) 5540 { 5541 sli4_eqe_t *eqe = (void *)buf; 5542 int32_t rc = 0; 5543 5544 if (!sli4 || !buf || !cq_id) { 5545 ocs_log_err(NULL, "bad parameters sli4=%p buf=%p cq_id=%p\n", 5546 sli4, buf, cq_id); 5547 return -1; 5548 } 5549 5550 switch (eqe->major_code) { 5551 case SLI4_MAJOR_CODE_STANDARD: 5552 *cq_id = eqe->resource_id; 5553 break; 5554 case SLI4_MAJOR_CODE_SENTINEL: 5555 ocs_log_debug(sli4->os, "sentinel EQE\n"); 5556 rc = 1; 5557 break; 5558 default: 5559 ocs_log_test(sli4->os, "Unsupported EQE: major %x minor %x\n", 5560 eqe->major_code, eqe->minor_code); 5561 rc = -1; 5562 } 5563 5564 return rc; 5565 } 5566 5567 /** 5568 * @ingroup sli 5569 * @brief Parse a CQ entry to retrieve the event type and the associated queue. 5570 * 5571 * @param sli4 SLI context. 5572 * @param cq CQ to process. 5573 * @param cqe Pointer to the CQ entry. 5574 * @param etype CQ event type. 5575 * @param q_id Queue ID associated with this completion message 5576 * (that is, MQ_ID, RQ_ID, and so on). 5577 * 5578 * @return 5579 * - 0 if call completed correctly and CQE status is SUCCESS. 5580 * - -1 if call failed (no CQE status). 5581 * - Other value if call completed correctly and return value is a CQE status value. 5582 */ 5583 int32_t 5584 sli_cq_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype, 5585 uint16_t *q_id) 5586 { 5587 int32_t rc = 0; 5588 5589 if (!sli4 || !cq || !cqe || !etype) { 5590 ocs_log_err(NULL, "bad parameters sli4=%p cq=%p cqe=%p etype=%p q_id=%p\n", 5591 sli4, cq, cqe, etype, q_id); 5592 return -1; 5593 } 5594 5595 if (cq->u.flag.is_mq) { 5596 sli4_mcqe_t *mcqe = (void *)cqe; 5597 5598 if (mcqe->ae) { 5599 *etype = SLI_QENTRY_ASYNC; 5600 } else { 5601 *etype = SLI_QENTRY_MQ; 5602 rc = sli_cqe_mq(mcqe); 5603 } 5604 *q_id = -1; 5605 } else if (SLI4_PORT_TYPE_FC == sli4->port_type) { 5606 rc = sli_fc_cqe_parse(sli4, cq, cqe, etype, q_id); 5607 } else { 5608 ocs_log_test(sli4->os, "implement CQE parsing type = %#x\n", 5609 sli4->port_type); 5610 rc = -1; 5611 } 5612 5613 return rc; 5614 } 5615 5616 /** 5617 * @ingroup sli 5618 * @brief Cause chip to enter an unrecoverable error state. 5619 * 5620 * @par Description 5621 * Cause chip to enter an unrecoverable error state. This is 5622 * used when detecting unexpected FW behavior so FW can be 5623 * hwted from the driver as soon as error is detected. 5624 * 5625 * @param sli4 SLI context. 5626 * @param dump Generate dump as part of reset. 5627 * 5628 * @return Returns 0 if call completed correctly, or -1 if call failed (unsupported chip). 5629 */ 5630 int32_t sli_raise_ue(sli4_t *sli4, uint8_t dump) 5631 { 5632 #define FDD 2 5633 if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) { 5634 switch(sli_get_asic_type(sli4)) { 5635 case SLI4_ASIC_TYPE_BE3: { 5636 sli_reg_write(sli4, SLI4_REG_SW_UE_CSR1, 0xffffffff); 5637 sli_reg_write(sli4, SLI4_REG_SW_UE_CSR2, 0); 5638 break; 5639 } 5640 case SLI4_ASIC_TYPE_SKYHAWK: { 5641 uint32_t value; 5642 value = ocs_config_read32(sli4->os, SLI4_SW_UE_REG); 5643 ocs_config_write32(sli4->os, SLI4_SW_UE_REG, (value | (1U << 24))); 5644 break; 5645 } 5646 default: 5647 ocs_log_test(sli4->os, "invalid asic type %d\n", sli_get_asic_type(sli4)); 5648 return -1; 5649 } 5650 } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) || 5651 (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4))) { 5652 if (FDD == dump) { 5653 sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, SLI4_SLIPORT_CONTROL_FDD | SLI4_SLIPORT_CONTROL_IP); 5654 } else { 5655 uint32_t value = SLI4_PHYDEV_CONTROL_FRST; 5656 if (dump == 1) { 5657 value |= SLI4_PHYDEV_CONTROL_DD; 5658 } 5659 sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, value); 5660 } 5661 } else { 5662 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4)); 5663 return -1; 5664 } 5665 return 0; 5666 } 5667 5668 /** 5669 * @ingroup sli 5670 * @brief Read the SLIPORT_STATUS register to check if a dump is present. 5671 * 5672 * @param sli4 SLI context. 5673 * 5674 * @return Returns 1 if the chip is ready, or 0 if the chip is not ready, 2 if fdp is present. 5675 */ 5676 int32_t sli_dump_is_ready(sli4_t *sli4) 5677 { 5678 int32_t rc = 0; 5679 uint32_t port_val; 5680 uint32_t bmbx_val; 5681 uint32_t uerr_lo; 5682 uint32_t uerr_hi; 5683 uint32_t uerr_mask_lo; 5684 uint32_t uerr_mask_hi; 5685 5686 if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) { 5687 /* for iftype=0, dump ready when UE is encountered */ 5688 uerr_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO); 5689 uerr_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI); 5690 uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO); 5691 uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI); 5692 if ((uerr_lo & ~uerr_mask_lo) || (uerr_hi & ~uerr_mask_hi)) { 5693 rc = 1; 5694 } 5695 5696 } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) || 5697 (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4))) { 5698 /* 5699 * Ensure that the port is ready AND the mailbox is 5700 * ready before signaling that the dump is ready to go. 5701 */ 5702 port_val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS); 5703 bmbx_val = sli_reg_read(sli4, SLI4_REG_BMBX); 5704 5705 if ((bmbx_val & SLI4_BMBX_RDY) && 5706 SLI4_PORT_STATUS_READY(port_val)) { 5707 if(SLI4_PORT_STATUS_DUMP_PRESENT(port_val)) { 5708 rc = 1; 5709 }else if( SLI4_PORT_STATUS_FDP_PRESENT(port_val)) { 5710 rc = 2; 5711 } 5712 } 5713 } else { 5714 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4)); 5715 return -1; 5716 } 5717 return rc; 5718 } 5719 5720 /** 5721 * @ingroup sli 5722 * @brief Read the SLIPORT_STATUS register to check if a dump is present. 5723 * 5724 * @param sli4 SLI context. 5725 * 5726 * @return 5727 * - 0 if call completed correctly and no dump is present. 5728 * - 1 if call completed and dump is present. 5729 * - -1 if call failed (unsupported chip). 5730 */ 5731 int32_t sli_dump_is_present(sli4_t *sli4) 5732 { 5733 uint32_t val; 5734 uint32_t ready; 5735 5736 if ((SLI4_IF_TYPE_LANCER_FC_ETH != sli_get_if_type(sli4)) && 5737 (SLI4_IF_TYPE_LANCER_G7 != sli_get_if_type(sli4))) { 5738 ocs_log_test(sli4->os, "Function only supported for I/F type 2"); 5739 return -1; 5740 } 5741 5742 /* If the chip is not ready, then there cannot be a dump */ 5743 ready = sli_wait_for_fw_ready(sli4, SLI4_INIT_PORT_DELAY_US); 5744 if (!ready) { 5745 return 0; 5746 } 5747 5748 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS); 5749 if (UINT32_MAX == val) { 5750 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n"); 5751 return -1; 5752 } else { 5753 return ((val & SLI4_PORT_STATUS_DIP) ? 1 : 0); 5754 } 5755 } 5756 5757 /** 5758 * @ingroup sli 5759 * @brief Read the SLIPORT_STATUS register to check if the reset required is set. 5760 * 5761 * @param sli4 SLI context. 5762 * 5763 * @return 5764 * - 0 if call completed correctly and reset is not required. 5765 * - 1 if call completed and reset is required. 5766 * - -1 if call failed. 5767 */ 5768 int32_t sli_reset_required(sli4_t *sli4) 5769 { 5770 uint32_t val; 5771 5772 if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) { 5773 ocs_log_test(sli4->os, "reset required N/A for iftype 0\n"); 5774 return 0; 5775 } 5776 5777 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS); 5778 if (UINT32_MAX == val) { 5779 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n"); 5780 return -1; 5781 } else { 5782 return ((val & SLI4_PORT_STATUS_RN) ? 1 : 0); 5783 } 5784 } 5785 5786 /** 5787 * @ingroup sli 5788 * @brief Read the SLIPORT_SEMAPHORE and SLIPORT_STATUS registers to check if 5789 * the port status indicates that a FW error has occurred. 5790 * 5791 * @param sli4 SLI context. 5792 * 5793 * @return 5794 * - 0 if call completed correctly and no FW error occurred. 5795 * - > 0 which indicates that a FW error has occurred. 5796 * - -1 if call failed. 5797 */ 5798 int32_t sli_fw_error_status(sli4_t *sli4) 5799 { 5800 uint32_t sliport_semaphore; 5801 int32_t rc = 0; 5802 5803 sliport_semaphore = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE); 5804 if (UINT32_MAX == sliport_semaphore) { 5805 ocs_log_err(sli4->os, "error reading SLIPORT_SEMAPHORE register\n"); 5806 return 1; 5807 } 5808 rc = (SLI4_PORT_SEMAPHORE_IN_ERR(sliport_semaphore) ? 1 : 0); 5809 5810 if (rc == 0) { 5811 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type || 5812 (SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type)) { 5813 uint32_t uerr_mask_lo, uerr_mask_hi; 5814 uint32_t uerr_status_lo, uerr_status_hi; 5815 5816 uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO); 5817 uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI); 5818 uerr_status_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO); 5819 uerr_status_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI); 5820 if ((uerr_mask_lo & uerr_status_lo) != 0 || 5821 (uerr_mask_hi & uerr_status_hi) != 0) { 5822 rc = 1; 5823 } 5824 } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type || 5825 SLI4_IF_TYPE_LANCER_G7 == sli4->if_type) { 5826 uint32_t sliport_status; 5827 5828 sliport_status = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS); 5829 rc = (SLI4_PORT_STATUS_ERROR(sliport_status) ? 1 : 0); 5830 } 5831 } 5832 return rc; 5833 } 5834 5835 /** 5836 * @ingroup sli 5837 * @brief Determine if the chip FW is in a ready state 5838 * 5839 * @param sli4 SLI context. 5840 * 5841 * @return 5842 * - 0 if call completed correctly and FW is not ready. 5843 * - 1 if call completed correctly and FW is ready. 5844 * - -1 if call failed. 5845 */ 5846 int32_t 5847 sli_fw_ready(sli4_t *sli4) 5848 { 5849 uint32_t val; 5850 int32_t rc = -1; 5851 5852 /* 5853 * Is firmware ready for operation? Check needed depends on IF_TYPE 5854 */ 5855 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type || 5856 SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type) { 5857 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE); 5858 rc = ((SLI4_PORT_SEMAPHORE_STATUS_POST_READY == 5859 SLI4_PORT_SEMAPHORE_PORT(val)) && 5860 (!SLI4_PORT_SEMAPHORE_IN_ERR(val)) ? 1 : 0); 5861 } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type || 5862 SLI4_IF_TYPE_LANCER_G7 == sli4->if_type) { 5863 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS); 5864 rc = (SLI4_PORT_STATUS_READY(val) ? 1 : 0); 5865 } 5866 return rc; 5867 } 5868 5869 /** 5870 * @ingroup sli 5871 * @brief Determine if the link can be configured 5872 * 5873 * @param sli4 SLI context. 5874 * 5875 * @return 5876 * - 0 if link is not configurable. 5877 * - 1 if link is configurable. 5878 */ 5879 int32_t sli_link_is_configurable(sli4_t *sli) 5880 { 5881 int32_t rc = 0; 5882 /* 5883 * Link config works on: Skyhawk and Lancer 5884 * Link config does not work on: LancerG6 5885 */ 5886 5887 switch (sli_get_asic_type(sli)) { 5888 case SLI4_ASIC_TYPE_SKYHAWK: 5889 case SLI4_ASIC_TYPE_LANCER: 5890 case SLI4_ASIC_TYPE_CORSAIR: 5891 rc = 1; 5892 break; 5893 case SLI4_ASIC_TYPE_LANCERG6: 5894 case SLI4_ASIC_TYPE_LANCERG7: 5895 case SLI4_ASIC_TYPE_BE3: 5896 default: 5897 rc = 0; 5898 break; 5899 } 5900 5901 return rc; 5902 5903 } 5904 5905 /* vim: set noexpandtab textwidth=120: */ 5906 5907 /** 5908 * @ingroup sli_fc 5909 * @brief Write an FCOE_WQ_CREATE command. 5910 * 5911 * @param sli4 SLI context. 5912 * @param buf Destination buffer for the command. 5913 * @param size Buffer size, in bytes. 5914 * @param qmem DMA memory for the queue. 5915 * @param cq_id Associated CQ_ID. 5916 * @param ulp The ULP to bind 5917 * 5918 * @note This creates a Version 0 message. 5919 * 5920 * @return Returns the number of bytes written. 5921 */ 5922 int32_t 5923 sli_cmd_fcoe_wq_create(sli4_t *sli4, void *buf, size_t size, 5924 ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp) 5925 { 5926 sli4_req_fcoe_wq_create_t *wq = NULL; 5927 uint32_t sli_config_off = 0; 5928 uint32_t p; 5929 uintptr_t addr; 5930 5931 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 5932 uint32_t payload_size; 5933 5934 /* Payload length must accommodate both request and response */ 5935 payload_size = max(sizeof(sli4_req_fcoe_wq_create_t), 5936 sizeof(sli4_res_common_create_queue_t)); 5937 5938 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 5939 NULL); 5940 } 5941 wq = (sli4_req_fcoe_wq_create_t *)((uint8_t *)buf + sli_config_off); 5942 5943 wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE; 5944 wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 5945 wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_t) - 5946 sizeof(sli4_req_hdr_t); 5947 /* valid values for number of pages: 1-4 (sec 4.5.1) */ 5948 wq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE); 5949 if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V0_MAX_PAGES)) { 5950 return 0; 5951 } 5952 5953 wq->cq_id = cq_id; 5954 5955 if (sli4->config.dual_ulp_capable) { 5956 wq->dua = 1; 5957 wq->bqu = 1; 5958 wq->ulp = ulp; 5959 } 5960 5961 for (p = 0, addr = qmem->phys; 5962 p < wq->num_pages; 5963 p++, addr += SLI_PAGE_SIZE) { 5964 wq->page_physical_address[p].low = ocs_addr32_lo(addr); 5965 wq->page_physical_address[p].high = ocs_addr32_hi(addr); 5966 } 5967 5968 return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_t)); 5969 } 5970 5971 /** 5972 * @ingroup sli_fc 5973 * @brief Write an FCOE_WQ_CREATE_V1 command. 5974 * 5975 * @param sli4 SLI context. 5976 * @param buf Destination buffer for the command. 5977 * @param size Buffer size, in bytes. 5978 * @param qmem DMA memory for the queue. 5979 * @param cq_id Associated CQ_ID. 5980 * @param ignored This parameter carries the ULP for WQ (ignored for V1) 5981 5982 * 5983 * @return Returns the number of bytes written. 5984 */ 5985 int32_t 5986 sli_cmd_fcoe_wq_create_v1(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem, 5987 uint16_t cq_id, uint16_t ignored) 5988 { 5989 sli4_req_fcoe_wq_create_v1_t *wq = NULL; 5990 uint32_t sli_config_off = 0; 5991 uint32_t p; 5992 uintptr_t addr; 5993 uint32_t page_size = 0; 5994 uint32_t page_bytes = 0; 5995 uint32_t n_wqe = 0; 5996 5997 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 5998 uint32_t payload_size; 5999 6000 /* Payload length must accommodate both request and response */ 6001 payload_size = max(sizeof(sli4_req_fcoe_wq_create_v1_t), 6002 sizeof(sli4_res_common_create_queue_t)); 6003 6004 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 6005 NULL); 6006 } 6007 wq = (sli4_req_fcoe_wq_create_v1_t *)((uint8_t *)buf + sli_config_off); 6008 6009 wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE; 6010 wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6011 wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_v1_t) - 6012 sizeof(sli4_req_hdr_t); 6013 wq->hdr.version = 1; 6014 6015 n_wqe = qmem->size / sli4->config.wqe_size; 6016 6017 /* This heuristic to determine the page size is simplistic 6018 * but could be made more sophisticated 6019 */ 6020 switch (qmem->size) { 6021 case 4096: 6022 case 8192: 6023 case 16384: 6024 case 32768: 6025 page_size = 1; 6026 break; 6027 case 65536: 6028 page_size = 2; 6029 break; 6030 case 131072: 6031 page_size = 4; 6032 break; 6033 case 262144: 6034 page_size = 8; 6035 break; 6036 case 524288: 6037 page_size = 10; 6038 break; 6039 default: 6040 return 0; 6041 } 6042 page_bytes = page_size * SLI_PAGE_SIZE; 6043 6044 /* valid values for number of pages: 1-8 */ 6045 wq->num_pages = sli_page_count(qmem->size, page_bytes); 6046 if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V1_MAX_PAGES)) { 6047 return 0; 6048 } 6049 6050 wq->cq_id = cq_id; 6051 6052 wq->page_size = page_size; 6053 6054 if (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) { 6055 wq->wqe_size = SLI4_WQE_EXT_SIZE; 6056 } else { 6057 wq->wqe_size = SLI4_WQE_SIZE; 6058 } 6059 6060 wq->wqe_count = n_wqe; 6061 6062 for (p = 0, addr = qmem->phys; 6063 p < wq->num_pages; 6064 p++, addr += page_bytes) { 6065 wq->page_physical_address[p].low = ocs_addr32_lo(addr); 6066 wq->page_physical_address[p].high = ocs_addr32_hi(addr); 6067 } 6068 6069 return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_v1_t)); 6070 } 6071 6072 /** 6073 * @ingroup sli_fc 6074 * @brief Write an FCOE_WQ_DESTROY command. 6075 * 6076 * @param sli4 SLI context. 6077 * @param buf Destination buffer for the command. 6078 * @param size Buffer size, in bytes. 6079 * @param wq_id WQ_ID. 6080 * 6081 * @return Returns the number of bytes written. 6082 */ 6083 int32_t 6084 sli_cmd_fcoe_wq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t wq_id) 6085 { 6086 sli4_req_fcoe_wq_destroy_t *wq = NULL; 6087 uint32_t sli_config_off = 0; 6088 6089 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 6090 uint32_t payload_size; 6091 6092 /* Payload length must accommodate both request and response */ 6093 payload_size = max(sizeof(sli4_req_fcoe_wq_destroy_t), 6094 sizeof(sli4_res_hdr_t)); 6095 6096 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 6097 NULL); 6098 } 6099 wq = (sli4_req_fcoe_wq_destroy_t *)((uint8_t *)buf + sli_config_off); 6100 6101 wq->hdr.opcode = SLI4_OPC_FCOE_WQ_DESTROY; 6102 wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6103 wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_destroy_t) - 6104 sizeof(sli4_req_hdr_t); 6105 6106 wq->wq_id = wq_id; 6107 6108 return(sli_config_off + sizeof(sli4_req_fcoe_wq_destroy_t)); 6109 } 6110 6111 /** 6112 * @ingroup sli_fc 6113 * @brief Write an FCOE_POST_SGL_PAGES command. 6114 * 6115 * @param sli4 SLI context. 6116 * @param buf Destination buffer for the command. 6117 * @param size Buffer size, in bytes. 6118 * @param xri starting XRI 6119 * @param xri_count XRI 6120 * @param page0 First SGL memory page. 6121 * @param page1 Second SGL memory page (optional). 6122 * @param dma DMA buffer for non-embedded mailbox command (options) 6123 * 6124 * if non-embedded mbx command is used, dma buffer must be at least (32 + xri_count*16) in length 6125 * 6126 * @return Returns the number of bytes written. 6127 */ 6128 int32_t 6129 sli_cmd_fcoe_post_sgl_pages(sli4_t *sli4, void *buf, size_t size, 6130 uint16_t xri, uint32_t xri_count, ocs_dma_t *page0[], ocs_dma_t *page1[], ocs_dma_t *dma) 6131 { 6132 sli4_req_fcoe_post_sgl_pages_t *post = NULL; 6133 uint32_t sli_config_off = 0; 6134 uint32_t i; 6135 6136 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 6137 uint32_t payload_size; 6138 6139 /* Payload length must accommodate both request and response */ 6140 payload_size = max(sizeof(sli4_req_fcoe_post_sgl_pages_t), 6141 sizeof(sli4_res_hdr_t)); 6142 6143 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 6144 dma); 6145 } 6146 if (dma) { 6147 post = dma->virt; 6148 ocs_memset(post, 0, dma->size); 6149 } else { 6150 post = (sli4_req_fcoe_post_sgl_pages_t *)((uint8_t *)buf + sli_config_off); 6151 } 6152 6153 post->hdr.opcode = SLI4_OPC_FCOE_POST_SGL_PAGES; 6154 post->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6155 /* payload size calculation 6156 * 4 = xri_start + xri_count 6157 * xri_count = # of XRI's registered 6158 * sizeof(uint64_t) = physical address size 6159 * 2 = # of physical addresses per page set 6160 */ 6161 post->hdr.request_length = 4 + (xri_count * (sizeof(uint64_t) * 2)); 6162 6163 post->xri_start = xri; 6164 post->xri_count = xri_count; 6165 6166 for (i = 0; i < xri_count; i++) { 6167 post->page_set[i].page0_low = ocs_addr32_lo(page0[i]->phys); 6168 post->page_set[i].page0_high = ocs_addr32_hi(page0[i]->phys); 6169 } 6170 6171 if (page1) { 6172 for (i = 0; i < xri_count; i++) { 6173 post->page_set[i].page1_low = ocs_addr32_lo(page1[i]->phys); 6174 post->page_set[i].page1_high = ocs_addr32_hi(page1[i]->phys); 6175 } 6176 } 6177 6178 return dma ? sli_config_off : (sli_config_off + sizeof(sli4_req_fcoe_post_sgl_pages_t)); 6179 } 6180 6181 /** 6182 * @ingroup sli_fc 6183 * @brief Write an FCOE_RQ_CREATE command. 6184 * 6185 * @param sli4 SLI context. 6186 * @param buf Destination buffer for the command. 6187 * @param size Buffer size, in bytes. 6188 * @param qmem DMA memory for the queue. 6189 * @param cq_id Associated CQ_ID. 6190 * @param ulp This parameter carries the ULP for the RQ 6191 * @param buffer_size Buffer size pointed to by each RQE. 6192 * 6193 * @note This creates a Version 0 message. 6194 * 6195 * @return Returns the number of bytes written. 6196 */ 6197 int32_t 6198 sli_cmd_fcoe_rq_create(sli4_t *sli4, void *buf, size_t size, 6199 ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp, uint16_t buffer_size) 6200 { 6201 sli4_req_fcoe_rq_create_t *rq = NULL; 6202 uint32_t sli_config_off = 0; 6203 uint32_t p; 6204 uintptr_t addr; 6205 6206 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 6207 uint32_t payload_size; 6208 6209 /* Payload length must accommodate both request and response */ 6210 payload_size = max(sizeof(sli4_req_fcoe_rq_create_t), 6211 sizeof(sli4_res_common_create_queue_t)); 6212 6213 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 6214 NULL); 6215 } 6216 rq = (sli4_req_fcoe_rq_create_t *)((uint8_t *)buf + sli_config_off); 6217 6218 rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE; 6219 rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6220 rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_t) - 6221 sizeof(sli4_req_hdr_t); 6222 /* valid values for number of pages: 1-8 (sec 4.5.6) */ 6223 rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE); 6224 if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V0_MAX_PAGES)) { 6225 ocs_log_test(sli4->os, "num_pages %d not valid\n", rq->num_pages); 6226 return 0; 6227 } 6228 6229 /* 6230 * RQE count is the log base 2 of the total number of entries 6231 */ 6232 rq->rqe_count = ocs_lg2(qmem->size / SLI4_FCOE_RQE_SIZE); 6233 6234 if ((buffer_size < SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE) || 6235 (buffer_size > SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE)) { 6236 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n", 6237 buffer_size, 6238 SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE, 6239 SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE); 6240 return -1; 6241 } 6242 rq->buffer_size = buffer_size; 6243 6244 rq->cq_id = cq_id; 6245 6246 if (sli4->config.dual_ulp_capable) { 6247 rq->dua = 1; 6248 rq->bqu = 1; 6249 rq->ulp = ulp; 6250 } 6251 6252 for (p = 0, addr = qmem->phys; 6253 p < rq->num_pages; 6254 p++, addr += SLI_PAGE_SIZE) { 6255 rq->page_physical_address[p].low = ocs_addr32_lo(addr); 6256 rq->page_physical_address[p].high = ocs_addr32_hi(addr); 6257 } 6258 6259 return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_t)); 6260 } 6261 6262 /** 6263 * @ingroup sli_fc 6264 * @brief Write an FCOE_RQ_CREATE_V1 command. 6265 * 6266 * @param sli4 SLI context. 6267 * @param buf Destination buffer for the command. 6268 * @param size Buffer size, in bytes. 6269 * @param qmem DMA memory for the queue. 6270 * @param cq_id Associated CQ_ID. 6271 * @param ulp This parameter carries the ULP for RQ (ignored for V1) 6272 * @param buffer_size Buffer size pointed to by each RQE. 6273 * 6274 * @note This creates a Version 0 message 6275 * 6276 * @return Returns the number of bytes written. 6277 */ 6278 int32_t 6279 sli_cmd_fcoe_rq_create_v1(sli4_t *sli4, void *buf, size_t size, 6280 ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp, 6281 uint16_t buffer_size) 6282 { 6283 sli4_req_fcoe_rq_create_v1_t *rq = NULL; 6284 uint32_t sli_config_off = 0; 6285 uint32_t p; 6286 uintptr_t addr; 6287 6288 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 6289 uint32_t payload_size; 6290 6291 /* Payload length must accommodate both request and response */ 6292 payload_size = max(sizeof(sli4_req_fcoe_rq_create_v1_t), 6293 sizeof(sli4_res_common_create_queue_t)); 6294 6295 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 6296 NULL); 6297 } 6298 rq = (sli4_req_fcoe_rq_create_v1_t *)((uint8_t *)buf + sli_config_off); 6299 6300 rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE; 6301 rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6302 rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v1_t) - 6303 sizeof(sli4_req_hdr_t); 6304 rq->hdr.version = 1; 6305 6306 /* Disable "no buffer warnings" to avoid Lancer bug */ 6307 rq->dnb = TRUE; 6308 6309 /* valid values for number of pages: 1-8 (sec 4.5.6) */ 6310 rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE); 6311 if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES)) { 6312 ocs_log_test(sli4->os, "num_pages %d not valid, max %d\n", 6313 rq->num_pages, SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES); 6314 return 0; 6315 } 6316 6317 /* 6318 * RQE count is the total number of entries (note not lg2(# entries)) 6319 */ 6320 rq->rqe_count = qmem->size / SLI4_FCOE_RQE_SIZE; 6321 6322 rq->rqe_size = SLI4_FCOE_RQE_SIZE_8; 6323 6324 rq->page_size = SLI4_FCOE_RQ_PAGE_SIZE_4096; 6325 6326 if ((buffer_size < sli4->config.rq_min_buf_size) || 6327 (buffer_size > sli4->config.rq_max_buf_size)) { 6328 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n", 6329 buffer_size, 6330 sli4->config.rq_min_buf_size, 6331 sli4->config.rq_max_buf_size); 6332 return -1; 6333 } 6334 rq->buffer_size = buffer_size; 6335 6336 rq->cq_id = cq_id; 6337 6338 for (p = 0, addr = qmem->phys; 6339 p < rq->num_pages; 6340 p++, addr += SLI_PAGE_SIZE) { 6341 rq->page_physical_address[p].low = ocs_addr32_lo(addr); 6342 rq->page_physical_address[p].high = ocs_addr32_hi(addr); 6343 } 6344 6345 return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_v1_t)); 6346 } 6347 6348 /** 6349 * @ingroup sli_fc 6350 * @brief Write an FCOE_RQ_DESTROY command. 6351 * 6352 * @param sli4 SLI context. 6353 * @param buf Destination buffer for the command. 6354 * @param size Buffer size, in bytes. 6355 * @param rq_id RQ_ID. 6356 * 6357 * @return Returns the number of bytes written. 6358 */ 6359 int32_t 6360 sli_cmd_fcoe_rq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t rq_id) 6361 { 6362 sli4_req_fcoe_rq_destroy_t *rq = NULL; 6363 uint32_t sli_config_off = 0; 6364 6365 if (SLI4_PORT_TYPE_FC == sli4->port_type) { 6366 uint32_t payload_size; 6367 6368 /* Payload length must accommodate both request and response */ 6369 payload_size = max(sizeof(sli4_req_fcoe_rq_destroy_t), 6370 sizeof(sli4_res_hdr_t)); 6371 6372 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, 6373 NULL); 6374 } 6375 rq = (sli4_req_fcoe_rq_destroy_t *)((uint8_t *)buf + sli_config_off); 6376 6377 rq->hdr.opcode = SLI4_OPC_FCOE_RQ_DESTROY; 6378 rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6379 rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_destroy_t) - 6380 sizeof(sli4_req_hdr_t); 6381 6382 rq->rq_id = rq_id; 6383 6384 return(sli_config_off + sizeof(sli4_req_fcoe_rq_destroy_t)); 6385 } 6386 6387 /** 6388 * @ingroup sli_fc 6389 * @brief Write an FCOE_READ_FCF_TABLE command. 6390 * 6391 * @note 6392 * The response of this command exceeds the size of an embedded 6393 * command and requires an external buffer with DMA capability to hold the results. 6394 * The caller should allocate the ocs_dma_t structure / memory. 6395 * 6396 * @param sli4 SLI context. 6397 * @param buf Destination buffer for the command. 6398 * @param size Buffer size, in bytes. 6399 * @param dma Pointer to DMA memory structure. This is allocated by the caller. 6400 * @param index FCF table index to retrieve. 6401 * 6402 * @return Returns the number of bytes written. 6403 */ 6404 int32_t 6405 sli_cmd_fcoe_read_fcf_table(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, uint16_t index) 6406 { 6407 sli4_req_fcoe_read_fcf_table_t *read_fcf = NULL; 6408 6409 if (SLI4_PORT_TYPE_FC != sli4->port_type) { 6410 ocs_log_test(sli4->os, "FCOE_READ_FCF_TABLE only supported on FC\n"); 6411 return -1; 6412 } 6413 6414 read_fcf = dma->virt; 6415 6416 ocs_memset(read_fcf, 0, sizeof(sli4_req_fcoe_read_fcf_table_t)); 6417 6418 read_fcf->hdr.opcode = SLI4_OPC_FCOE_READ_FCF_TABLE; 6419 read_fcf->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6420 read_fcf->hdr.request_length = dma->size - 6421 sizeof(sli4_req_fcoe_read_fcf_table_t); 6422 read_fcf->fcf_index = index; 6423 6424 return sli_cmd_sli_config(sli4, buf, size, 0, dma); 6425 } 6426 6427 /** 6428 * @ingroup sli_fc 6429 * @brief Write an FCOE_POST_HDR_TEMPLATES command. 6430 * 6431 * @param sli4 SLI context. 6432 * @param buf Destination buffer for the command. 6433 * @param size Buffer size, in bytes. 6434 * @param dma Pointer to DMA memory structure. This is allocated by the caller. 6435 * @param rpi Starting RPI index for the header templates. 6436 * @param payload_dma Pointer to DMA memory used to hold larger descriptor counts. 6437 * 6438 * @return Returns the number of bytes written. 6439 */ 6440 int32_t 6441 sli_cmd_fcoe_post_hdr_templates(sli4_t *sli4, void *buf, size_t size, 6442 ocs_dma_t *dma, uint16_t rpi, ocs_dma_t *payload_dma) 6443 { 6444 sli4_req_fcoe_post_hdr_templates_t *template = NULL; 6445 uint32_t sli_config_off = 0; 6446 uintptr_t phys = 0; 6447 uint32_t i = 0; 6448 uint32_t page_count; 6449 uint32_t payload_size; 6450 6451 page_count = sli_page_count(dma->size, SLI_PAGE_SIZE); 6452 6453 payload_size = sizeof(sli4_req_fcoe_post_hdr_templates_t) + 6454 page_count * sizeof(sli4_physical_page_descriptor_t); 6455 6456 if (page_count > 16) { 6457 /* We can't fit more than 16 descriptors into an embedded mailbox 6458 command, it has to be non-embedded */ 6459 if (ocs_dma_alloc(sli4->os, payload_dma, payload_size, 4)) { 6460 ocs_log_err(sli4->os, "mailbox payload memory allocation fail\n"); 6461 return 0; 6462 } 6463 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, payload_dma); 6464 template = (sli4_req_fcoe_post_hdr_templates_t *)payload_dma->virt; 6465 } else { 6466 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, NULL); 6467 template = (sli4_req_fcoe_post_hdr_templates_t *)((uint8_t *)buf + sli_config_off); 6468 } 6469 6470 if (UINT16_MAX == rpi) { 6471 rpi = sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0]; 6472 } 6473 6474 template->hdr.opcode = SLI4_OPC_FCOE_POST_HDR_TEMPLATES; 6475 template->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6476 template->hdr.request_length = sizeof(sli4_req_fcoe_post_hdr_templates_t) - 6477 sizeof(sli4_req_hdr_t); 6478 6479 template->rpi_offset = rpi; 6480 template->page_count = page_count; 6481 phys = dma->phys; 6482 for (i = 0; i < template->page_count; i++) { 6483 template->page_descriptor[i].low = ocs_addr32_lo(phys); 6484 template->page_descriptor[i].high = ocs_addr32_hi(phys); 6485 6486 phys += SLI_PAGE_SIZE; 6487 } 6488 6489 return(sli_config_off + payload_size); 6490 } 6491 6492 int32_t 6493 sli_cmd_fcoe_rediscover_fcf(sli4_t *sli4, void *buf, size_t size, uint16_t index) 6494 { 6495 sli4_req_fcoe_rediscover_fcf_t *redisc = NULL; 6496 uint32_t sli_config_off = 0; 6497 6498 sli_config_off = sli_cmd_sli_config(sli4, buf, size, 6499 sizeof(sli4_req_fcoe_rediscover_fcf_t), 6500 NULL); 6501 6502 redisc = (sli4_req_fcoe_rediscover_fcf_t *)((uint8_t *)buf + sli_config_off); 6503 6504 redisc->hdr.opcode = SLI4_OPC_FCOE_REDISCOVER_FCF; 6505 redisc->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 6506 redisc->hdr.request_length = sizeof(sli4_req_fcoe_rediscover_fcf_t) - 6507 sizeof(sli4_req_hdr_t); 6508 6509 if (index == UINT16_MAX) { 6510 redisc->fcf_count = 0; 6511 } else { 6512 redisc->fcf_count = 1; 6513 redisc->fcf_index[0] = index; 6514 } 6515 6516 return(sli_config_off + sizeof(sli4_req_fcoe_rediscover_fcf_t)); 6517 } 6518 6519 /** 6520 * @ingroup sli_fc 6521 * @brief Write an ABORT_WQE work queue entry. 6522 * 6523 * @param sli4 SLI context. 6524 * @param buf Destination buffer for the WQE. 6525 * @param size Buffer size, in bytes. 6526 * @param type Abort type, such as XRI, abort tag, and request tag. 6527 * @param send_abts Boolean to cause the hardware to automatically generate an ABTS. 6528 * @param ids ID of IOs to abort. 6529 * @param mask Mask applied to the ID values to abort. 6530 * @param tag Tag value associated with this abort. 6531 * @param cq_id The id of the completion queue where the WQE response is sent. 6532 * @param dnrx When set to 1, this field indicates that the SLI Port must not return the associated XRI to the SLI 6533 * Port's optimized write XRI pool. 6534 * 6535 * @return Returns 0 on success, or a non-zero value on failure. 6536 */ 6537 int32_t 6538 sli_abort_wqe(sli4_t *sli4, void *buf, size_t size, sli4_abort_type_e type, uint32_t send_abts, 6539 uint32_t ids, uint32_t mask, uint16_t tag, uint16_t cq_id) 6540 { 6541 sli4_abort_wqe_t *abort = buf; 6542 6543 ocs_memset(buf, 0, size); 6544 6545 switch (type) { 6546 case SLI_ABORT_XRI: 6547 abort->criteria = SLI4_ABORT_CRITERIA_XRI_TAG; 6548 if (mask) { 6549 ocs_log_warn(sli4->os, "warning non-zero mask %#x when aborting XRI %#x\n", mask, ids); 6550 mask = 0; 6551 } 6552 break; 6553 case SLI_ABORT_ABORT_ID: 6554 abort->criteria = SLI4_ABORT_CRITERIA_ABORT_TAG; 6555 break; 6556 case SLI_ABORT_REQUEST_ID: 6557 abort->criteria = SLI4_ABORT_CRITERIA_REQUEST_TAG; 6558 break; 6559 default: 6560 ocs_log_test(sli4->os, "unsupported type %#x\n", type); 6561 return -1; 6562 } 6563 6564 abort->ia = send_abts ? 0 : 1; 6565 6566 /* Suppress ABTS retries */ 6567 abort->ir = 1; 6568 6569 abort->t_mask = mask; 6570 abort->t_tag = ids; 6571 abort->command = SLI4_WQE_ABORT; 6572 abort->request_tag = tag; 6573 abort->qosd = TRUE; 6574 abort->cq_id = cq_id; 6575 abort->cmd_type = SLI4_CMD_ABORT_WQE; 6576 6577 return 0; 6578 } 6579 6580 /** 6581 * @ingroup sli_fc 6582 * @brief Write an ELS_REQUEST64_WQE work queue entry. 6583 * 6584 * @param sli4 SLI context. 6585 * @param buf Destination buffer for the WQE. 6586 * @param size Buffer size, in bytes. 6587 * @param sgl DMA memory for the ELS request. 6588 * @param req_type ELS request type. 6589 * @param req_len Length of ELS request in bytes. 6590 * @param max_rsp_len Max length of ELS response in bytes. 6591 * @param timeout Time, in seconds, before an IO times out. Zero means 2 * R_A_TOV. 6592 * @param xri XRI for this exchange. 6593 * @param tag IO tag value. 6594 * @param cq_id The id of the completion queue where the WQE response is sent. 6595 * @param rnode Destination of ELS request (that is, the remote node). 6596 * 6597 * @return Returns 0 on success, or a non-zero value on failure. 6598 */ 6599 int32_t 6600 sli_els_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint8_t req_type, 6601 uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout, 6602 uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode) 6603 { 6604 sli4_els_request64_wqe_t *els = buf; 6605 sli4_sge_t *sge = sgl->virt; 6606 uint8_t is_fabric = FALSE; 6607 6608 ocs_memset(buf, 0, size); 6609 6610 if (sli4->config.sgl_pre_registered) { 6611 els->xbl = FALSE; 6612 6613 els->dbde = TRUE; 6614 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BDE_64; 6615 6616 els->els_request_payload.buffer_length = req_len; 6617 els->els_request_payload.u.data.buffer_address_low = sge[0].buffer_address_low; 6618 els->els_request_payload.u.data.buffer_address_high = sge[0].buffer_address_high; 6619 } else { 6620 els->xbl = TRUE; 6621 6622 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BLP; 6623 6624 els->els_request_payload.buffer_length = 2 * sizeof(sli4_sge_t); 6625 els->els_request_payload.u.blp.sgl_segment_address_low = ocs_addr32_lo(sgl->phys); 6626 els->els_request_payload.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys); 6627 } 6628 6629 els->els_request_payload_length = req_len; 6630 els->max_response_payload_length = max_rsp_len; 6631 6632 els->xri_tag = xri; 6633 els->timer = timeout; 6634 els->class = SLI4_ELS_REQUEST64_CLASS_3; 6635 6636 els->command = SLI4_WQE_ELS_REQUEST64; 6637 6638 els->request_tag = tag; 6639 6640 if (rnode->node_group) { 6641 els->hlm = TRUE; 6642 els->remote_id = rnode->fc_id & 0x00ffffff; 6643 } 6644 6645 els->iod = SLI4_ELS_REQUEST64_DIR_READ; 6646 6647 els->qosd = TRUE; 6648 6649 /* figure out the ELS_ID value from the request buffer */ 6650 6651 switch (req_type) { 6652 case FC_ELS_CMD_LOGO: 6653 els->els_id = SLI4_ELS_REQUEST64_LOGO; 6654 if (rnode->attached) { 6655 els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 6656 els->context_tag = rnode->indicator; 6657 } else { 6658 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 6659 els->context_tag = rnode->sport->indicator; 6660 } 6661 if (FC_ADDR_FABRIC == rnode->fc_id) { 6662 is_fabric = TRUE; 6663 } 6664 break; 6665 case FC_ELS_CMD_FDISC: 6666 if (FC_ADDR_FABRIC == rnode->fc_id) { 6667 is_fabric = TRUE; 6668 } 6669 if (0 == rnode->sport->fc_id) { 6670 els->els_id = SLI4_ELS_REQUEST64_FDISC; 6671 is_fabric = TRUE; 6672 } else { 6673 els->els_id = SLI4_ELS_REQUEST64_OTHER; 6674 } 6675 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 6676 els->context_tag = rnode->sport->indicator; 6677 els->sp = TRUE; 6678 break; 6679 case FC_ELS_CMD_FLOGI: 6680 els->els_id = SLI4_ELS_REQUEST64_FLOGIN; 6681 is_fabric = TRUE; 6682 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) { 6683 if (!rnode->sport->domain) { 6684 ocs_log_test(sli4->os, "invalid domain handle\n"); 6685 return -1; 6686 } 6687 /* 6688 * IF_TYPE 0 skips INIT_VFI/INIT_VPI and therefore must use the 6689 * FCFI here 6690 */ 6691 els->ct = SLI4_ELS_REQUEST64_CONTEXT_FCFI; 6692 els->context_tag = rnode->sport->domain->fcf_indicator; 6693 els->sp = TRUE; 6694 } else { 6695 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 6696 els->context_tag = rnode->sport->indicator; 6697 6698 /* 6699 * Set SP here ... we haven't done a REG_VPI yet 6700 * TODO: need to maybe not set this when we have 6701 * completed VFI/VPI registrations ... 6702 * 6703 * Use the FC_ID of the SPORT if it has been allocated, otherwise 6704 * use an S_ID of zero. 6705 */ 6706 els->sp = TRUE; 6707 if (rnode->sport->fc_id != UINT32_MAX) { 6708 els->sid = rnode->sport->fc_id; 6709 } 6710 } 6711 break; 6712 case FC_ELS_CMD_PLOGI: 6713 els->els_id = SLI4_ELS_REQUEST64_PLOGI; 6714 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 6715 els->context_tag = rnode->sport->indicator; 6716 break; 6717 case FC_ELS_CMD_SCR: 6718 els->els_id = SLI4_ELS_REQUEST64_OTHER; 6719 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 6720 els->context_tag = rnode->sport->indicator; 6721 break; 6722 default: 6723 els->els_id = SLI4_ELS_REQUEST64_OTHER; 6724 if (rnode->attached) { 6725 els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 6726 els->context_tag = rnode->indicator; 6727 } else { 6728 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 6729 els->context_tag = rnode->sport->indicator; 6730 } 6731 break; 6732 } 6733 6734 if (is_fabric) { 6735 els->cmd_type = SLI4_ELS_REQUEST64_CMD_FABRIC; 6736 } else { 6737 els->cmd_type = SLI4_ELS_REQUEST64_CMD_NON_FABRIC; 6738 } 6739 6740 els->cq_id = cq_id; 6741 6742 if (SLI4_ELS_REQUEST64_CONTEXT_RPI != els->ct) { 6743 els->remote_id = rnode->fc_id; 6744 } 6745 if (SLI4_ELS_REQUEST64_CONTEXT_VPI == els->ct) { 6746 els->temporary_rpi = rnode->indicator; 6747 } 6748 6749 return 0; 6750 } 6751 6752 /** 6753 * @ingroup sli_fc 6754 * @brief Write an FCP_ICMND64_WQE work queue entry. 6755 * 6756 * @param sli4 SLI context. 6757 * @param buf Destination buffer for the WQE. 6758 * @param size Buffer size, in bytes. 6759 * @param sgl DMA memory for the scatter gather list. 6760 * @param xri XRI for this exchange. 6761 * @param tag IO tag value. 6762 * @param cq_id The id of the completion queue where the WQE response is sent. 6763 * @param rpi remote node indicator (RPI) 6764 * @param rnode Destination request (that is, the remote node). 6765 * @param timeout Time, in seconds, before an IO times out. Zero means no timeout. 6766 * 6767 * @return Returns 0 on success, or a non-zero value on failure. 6768 */ 6769 int32_t 6770 sli_fcp_icmnd64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, 6771 uint16_t xri, uint16_t tag, uint16_t cq_id, 6772 uint32_t rpi, ocs_remote_node_t *rnode, uint8_t timeout) 6773 { 6774 sli4_fcp_icmnd64_wqe_t *icmnd = buf; 6775 sli4_sge_t *sge = NULL; 6776 6777 ocs_memset(buf, 0, size); 6778 6779 if (!sgl || !sgl->virt) { 6780 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n", 6781 sgl, sgl ? sgl->virt : NULL); 6782 return -1; 6783 } 6784 sge = sgl->virt; 6785 6786 if (sli4->config.sgl_pre_registered) { 6787 icmnd->xbl = FALSE; 6788 6789 icmnd->dbde = TRUE; 6790 icmnd->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 6791 6792 icmnd->bde.buffer_length = sge[0].buffer_length; 6793 icmnd->bde.u.data.buffer_address_low = sge[0].buffer_address_low; 6794 icmnd->bde.u.data.buffer_address_high = sge[0].buffer_address_high; 6795 } else { 6796 icmnd->xbl = TRUE; 6797 6798 icmnd->bde.bde_type = SLI4_BDE_TYPE_BLP; 6799 6800 icmnd->bde.buffer_length = sgl->size; 6801 icmnd->bde.u.blp.sgl_segment_address_low = ocs_addr32_lo(sgl->phys); 6802 icmnd->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys); 6803 } 6804 6805 icmnd->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length; 6806 icmnd->xri_tag = xri; 6807 icmnd->context_tag = rpi; 6808 icmnd->timer = timeout; 6809 6810 icmnd->pu = 2; /* WQE word 4 contains read transfer length */ 6811 icmnd->class = SLI4_ELS_REQUEST64_CLASS_3; 6812 icmnd->command = SLI4_WQE_FCP_ICMND64; 6813 icmnd->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 6814 6815 icmnd->abort_tag = xri; 6816 6817 icmnd->request_tag = tag; 6818 icmnd->len_loc = 3; 6819 if (rnode->node_group) { 6820 icmnd->hlm = TRUE; 6821 icmnd->remote_n_port_id = rnode->fc_id & 0x00ffffff; 6822 } 6823 if (((ocs_node_t *)rnode->node)->fcp2device) { 6824 icmnd->erp = TRUE; 6825 } 6826 icmnd->cmd_type = SLI4_CMD_FCP_ICMND64_WQE; 6827 icmnd->cq_id = cq_id; 6828 6829 return 0; 6830 } 6831 6832 /** 6833 * @ingroup sli_fc 6834 * @brief Write an FCP_IREAD64_WQE work queue entry. 6835 * 6836 * @param sli4 SLI context. 6837 * @param buf Destination buffer for the WQE. 6838 * @param size Buffer size, in bytes. 6839 * @param sgl DMA memory for the scatter gather list. 6840 * @param first_data_sge Index of first data sge (used if perf hints are enabled) 6841 * @param xfer_len Data transfer length. 6842 * @param xri XRI for this exchange. 6843 * @param tag IO tag value. 6844 * @param cq_id The id of the completion queue where the WQE response is sent. 6845 * @param rpi remote node indicator (RPI) 6846 * @param rnode Destination request (i.e. remote node). 6847 * @param dif T10 DIF operation, or 0 to disable. 6848 * @param bs T10 DIF block size, or 0 if DIF is disabled. 6849 * @param timeout Time, in seconds, before an IO times out. Zero means no timeout. 6850 * 6851 * @return Returns 0 on success, or a non-zero value on failure. 6852 */ 6853 int32_t 6854 sli_fcp_iread64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge, 6855 uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id, 6856 uint32_t rpi, ocs_remote_node_t *rnode, 6857 uint8_t dif, uint8_t bs, uint8_t timeout) 6858 { 6859 sli4_fcp_iread64_wqe_t *iread = buf; 6860 sli4_sge_t *sge = NULL; 6861 6862 ocs_memset(buf, 0, size); 6863 6864 if (!sgl || !sgl->virt) { 6865 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n", 6866 sgl, sgl ? sgl->virt : NULL); 6867 return -1; 6868 } 6869 sge = sgl->virt; 6870 6871 if (sli4->config.sgl_pre_registered) { 6872 iread->xbl = FALSE; 6873 6874 iread->dbde = TRUE; 6875 iread->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 6876 6877 iread->bde.buffer_length = sge[0].buffer_length; 6878 iread->bde.u.data.buffer_address_low = sge[0].buffer_address_low; 6879 iread->bde.u.data.buffer_address_high = sge[0].buffer_address_high; 6880 } else { 6881 iread->xbl = TRUE; 6882 6883 iread->bde.bde_type = SLI4_BDE_TYPE_BLP; 6884 6885 iread->bde.buffer_length = sgl->size; 6886 iread->bde.u.blp.sgl_segment_address_low = ocs_addr32_lo(sgl->phys); 6887 iread->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys); 6888 6889 /* fill out fcp_cmnd buffer len and change resp buffer to be of type 6890 * "skip" (note: response will still be written to sge[1] if necessary) */ 6891 iread->fcp_cmd_buffer_length = sge[0].buffer_length; 6892 sge[1].sge_type = SLI4_SGE_TYPE_SKIP; 6893 } 6894 6895 iread->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length; 6896 iread->total_transfer_length = xfer_len; 6897 6898 iread->xri_tag = xri; 6899 iread->context_tag = rpi; 6900 6901 iread->timer = timeout; 6902 6903 iread->pu = 2; /* WQE word 4 contains read transfer length */ 6904 iread->class = SLI4_ELS_REQUEST64_CLASS_3; 6905 iread->command = SLI4_WQE_FCP_IREAD64; 6906 iread->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 6907 iread->dif = dif; 6908 iread->bs = bs; 6909 6910 iread->abort_tag = xri; 6911 6912 iread->request_tag = tag; 6913 iread->len_loc = 3; 6914 if (rnode->node_group) { 6915 iread->hlm = TRUE; 6916 iread->remote_n_port_id = rnode->fc_id & 0x00ffffff; 6917 } 6918 if (((ocs_node_t *)rnode->node)->fcp2device) { 6919 iread->erp = TRUE; 6920 } 6921 iread->iod = 1; 6922 iread->cmd_type = SLI4_CMD_FCP_IREAD64_WQE; 6923 iread->cq_id = cq_id; 6924 6925 if (sli4->config.perf_hint) { 6926 iread->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64; 6927 iread->first_data_bde.buffer_length = sge[first_data_sge].buffer_length; 6928 iread->first_data_bde.u.data.buffer_address_low = sge[first_data_sge].buffer_address_low; 6929 iread->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high; 6930 } 6931 6932 return 0; 6933 } 6934 6935 /** 6936 * @ingroup sli_fc 6937 * @brief Write an FCP_IWRITE64_WQE work queue entry. 6938 * 6939 * @param sli4 SLI context. 6940 * @param buf Destination buffer for the WQE. 6941 * @param size Buffer size, in bytes. 6942 * @param sgl DMA memory for the scatter gather list. 6943 * @param first_data_sge Index of first data sge (used if perf hints are enabled) 6944 * @param xfer_len Data transfer length. 6945 * @param first_burst The number of first burst bytes 6946 * @param xri XRI for this exchange. 6947 * @param tag IO tag value. 6948 * @param cq_id The id of the completion queue where the WQE response is sent. 6949 * @param rpi remote node indicator (RPI) 6950 * @param rnode Destination request (i.e. remote node) 6951 * @param dif T10 DIF operation, or 0 to disable 6952 * @param bs T10 DIF block size, or 0 if DIF is disabled 6953 * @param timeout Time, in seconds, before an IO times out. Zero means no timeout. 6954 * 6955 * @return Returns 0 on success, or a non-zero value on failure. 6956 */ 6957 int32_t 6958 sli_fcp_iwrite64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge, 6959 uint32_t xfer_len, uint32_t first_burst, uint16_t xri, uint16_t tag, uint16_t cq_id, 6960 uint32_t rpi, ocs_remote_node_t *rnode, 6961 uint8_t dif, uint8_t bs, uint8_t timeout) 6962 { 6963 sli4_fcp_iwrite64_wqe_t *iwrite = buf; 6964 sli4_sge_t *sge = NULL; 6965 6966 ocs_memset(buf, 0, size); 6967 6968 if (!sgl || !sgl->virt) { 6969 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n", 6970 sgl, sgl ? sgl->virt : NULL); 6971 return -1; 6972 } 6973 sge = sgl->virt; 6974 6975 if (sli4->config.sgl_pre_registered) { 6976 iwrite->xbl = FALSE; 6977 6978 iwrite->dbde = TRUE; 6979 iwrite->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 6980 6981 iwrite->bde.buffer_length = sge[0].buffer_length; 6982 iwrite->bde.u.data.buffer_address_low = sge[0].buffer_address_low; 6983 iwrite->bde.u.data.buffer_address_high = sge[0].buffer_address_high; 6984 } else { 6985 iwrite->xbl = TRUE; 6986 6987 iwrite->bde.bde_type = SLI4_BDE_TYPE_BLP; 6988 6989 iwrite->bde.buffer_length = sgl->size; 6990 iwrite->bde.u.blp.sgl_segment_address_low = ocs_addr32_lo(sgl->phys); 6991 iwrite->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys); 6992 6993 /* fill out fcp_cmnd buffer len and change resp buffer to be of type 6994 * "skip" (note: response will still be written to sge[1] if necessary) */ 6995 iwrite->fcp_cmd_buffer_length = sge[0].buffer_length; 6996 sge[1].sge_type = SLI4_SGE_TYPE_SKIP; 6997 } 6998 6999 iwrite->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length; 7000 iwrite->total_transfer_length = xfer_len; 7001 iwrite->initial_transfer_length = MIN(xfer_len, first_burst); 7002 7003 iwrite->xri_tag = xri; 7004 iwrite->context_tag = rpi; 7005 7006 iwrite->timer = timeout; 7007 7008 iwrite->pu = 2; /* WQE word 4 contains read transfer length */ 7009 iwrite->class = SLI4_ELS_REQUEST64_CLASS_3; 7010 iwrite->command = SLI4_WQE_FCP_IWRITE64; 7011 iwrite->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 7012 iwrite->dif = dif; 7013 iwrite->bs = bs; 7014 7015 iwrite->abort_tag = xri; 7016 7017 iwrite->request_tag = tag; 7018 iwrite->len_loc = 3; 7019 if (rnode->node_group) { 7020 iwrite->hlm = TRUE; 7021 iwrite->remote_n_port_id = rnode->fc_id & 0x00ffffff; 7022 } 7023 if (((ocs_node_t *)rnode->node)->fcp2device) { 7024 iwrite->erp = TRUE; 7025 } 7026 iwrite->cmd_type = SLI4_CMD_FCP_IWRITE64_WQE; 7027 iwrite->cq_id = cq_id; 7028 7029 if (sli4->config.perf_hint) { 7030 iwrite->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7031 iwrite->first_data_bde.buffer_length = sge[first_data_sge].buffer_length; 7032 iwrite->first_data_bde.u.data.buffer_address_low = sge[first_data_sge].buffer_address_low; 7033 iwrite->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high; 7034 } 7035 7036 return 0; 7037 } 7038 7039 /** 7040 * @ingroup sli_fc 7041 * @brief Write an FCP_TRECEIVE64_WQE work queue entry. 7042 * 7043 * @param sli4 SLI context. 7044 * @param buf Destination buffer for the WQE. 7045 * @param size Buffer size, in bytes. 7046 * @param sgl DMA memory for the Scatter-Gather List. 7047 * @param first_data_sge Index of first data sge (used if perf hints are enabled) 7048 * @param relative_off Relative offset of the IO (if any). 7049 * @param xfer_len Data transfer length. 7050 * @param xri XRI for this exchange. 7051 * @param tag IO tag value. 7052 * @param xid OX_ID for the exchange. 7053 * @param cq_id The id of the completion queue where the WQE response is sent. 7054 * @param rpi remote node indicator (RPI) 7055 * @param rnode Destination request (i.e. remote node). 7056 * @param flags Optional attributes, including: 7057 * - ACTIVE - IO is already active. 7058 * - AUTO RSP - Automatically generate a good FCP_RSP. 7059 * @param dif T10 DIF operation, or 0 to disable. 7060 * @param bs T10 DIF block size, or 0 if DIF is disabled. 7061 * @param csctl value of csctl field. 7062 * @param app_id value for VM application header. 7063 * 7064 * @return Returns 0 on success, or a non-zero value on failure. 7065 */ 7066 int32_t 7067 sli_fcp_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge, 7068 uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id, 7069 uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags, uint8_t dif, uint8_t bs, 7070 uint8_t csctl, uint32_t app_id) 7071 { 7072 sli4_fcp_treceive64_wqe_t *trecv = buf; 7073 sli4_fcp_128byte_wqe_t *trecv_128 = buf; 7074 sli4_sge_t *sge = NULL; 7075 7076 ocs_memset(buf, 0, size); 7077 7078 if (!sgl || !sgl->virt) { 7079 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n", 7080 sgl, sgl ? sgl->virt : NULL); 7081 return -1; 7082 } 7083 sge = sgl->virt; 7084 7085 if (sli4->config.sgl_pre_registered) { 7086 trecv->xbl = FALSE; 7087 7088 trecv->dbde = TRUE; 7089 trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7090 7091 trecv->bde.buffer_length = sge[0].buffer_length; 7092 trecv->bde.u.data.buffer_address_low = sge[0].buffer_address_low; 7093 trecv->bde.u.data.buffer_address_high = sge[0].buffer_address_high; 7094 7095 trecv->payload_offset_length = sge[0].buffer_length; 7096 } else { 7097 trecv->xbl = TRUE; 7098 7099 /* if data is a single physical address, use a BDE */ 7100 if (!dif && (xfer_len <= sge[2].buffer_length)) { 7101 trecv->dbde = TRUE; 7102 trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7103 7104 trecv->bde.buffer_length = sge[2].buffer_length; 7105 trecv->bde.u.data.buffer_address_low = sge[2].buffer_address_low; 7106 trecv->bde.u.data.buffer_address_high = sge[2].buffer_address_high; 7107 } else { 7108 trecv->bde.bde_type = SLI4_BDE_TYPE_BLP; 7109 trecv->bde.buffer_length = sgl->size; 7110 trecv->bde.u.blp.sgl_segment_address_low = ocs_addr32_lo(sgl->phys); 7111 trecv->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys); 7112 } 7113 } 7114 7115 trecv->relative_offset = relative_off; 7116 7117 if (flags & SLI4_IO_CONTINUATION) { 7118 trecv->xc = TRUE; 7119 } 7120 trecv->xri_tag = xri; 7121 7122 trecv->context_tag = rpi; 7123 7124 trecv->pu = TRUE; /* WQE uses relative offset */ 7125 7126 if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) { 7127 trecv->ar = TRUE; 7128 } 7129 7130 trecv->command = SLI4_WQE_FCP_TRECEIVE64; 7131 trecv->class = SLI4_ELS_REQUEST64_CLASS_3; 7132 trecv->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 7133 trecv->dif = dif; 7134 trecv->bs = bs; 7135 7136 trecv->remote_xid = xid; 7137 7138 trecv->request_tag = tag; 7139 7140 trecv->iod = 1; 7141 7142 trecv->len_loc = 0x2; 7143 7144 if (rnode->node_group) { 7145 trecv->hlm = TRUE; 7146 trecv->dword5.dword = rnode->fc_id & 0x00ffffff; 7147 } 7148 7149 trecv->cmd_type = SLI4_CMD_FCP_TRECEIVE64_WQE; 7150 7151 trecv->cq_id = cq_id; 7152 7153 trecv->fcp_data_receive_length = xfer_len; 7154 7155 if (sli4->config.perf_hint) { 7156 trecv->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7157 trecv->first_data_bde.buffer_length = sge[first_data_sge].buffer_length; 7158 trecv->first_data_bde.u.data.buffer_address_low = sge[first_data_sge].buffer_address_low; 7159 trecv->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high; 7160 } 7161 7162 /* The upper 7 bits of csctl is the priority */ 7163 if (csctl & SLI4_MASK_CCP) { 7164 trecv->ccpe = 1; 7165 trecv->ccp = (csctl & SLI4_MASK_CCP); 7166 } 7167 7168 if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trecv->eat) { 7169 trecv->app_id_valid = 1; 7170 trecv->wqes = 1; 7171 trecv_128->dw[31] = app_id; 7172 } 7173 return 0; 7174 } 7175 7176 /** 7177 * @ingroup sli_fc 7178 * @brief Write an FCP_CONT_TRECEIVE64_WQE work queue entry. 7179 * 7180 * @param sli4 SLI context. 7181 * @param buf Destination buffer for the WQE. 7182 * @param size Buffer size, in bytes. 7183 * @param sgl DMA memory for the Scatter-Gather List. 7184 * @param first_data_sge Index of first data sge (used if perf hints are enabled) 7185 * @param relative_off Relative offset of the IO (if any). 7186 * @param xfer_len Data transfer length. 7187 * @param xri XRI for this exchange. 7188 * @param sec_xri Secondary XRI for this exchange. (BZ 161832 workaround) 7189 * @param tag IO tag value. 7190 * @param xid OX_ID for the exchange. 7191 * @param cq_id The id of the completion queue where the WQE response is sent. 7192 * @param rpi remote node indicator (RPI) 7193 * @param rnode Destination request (i.e. remote node). 7194 * @param flags Optional attributes, including: 7195 * - ACTIVE - IO is already active. 7196 * - AUTO RSP - Automatically generate a good FCP_RSP. 7197 * @param dif T10 DIF operation, or 0 to disable. 7198 * @param bs T10 DIF block size, or 0 if DIF is disabled. 7199 * @param csctl value of csctl field. 7200 * @param app_id value for VM application header. 7201 * 7202 * @return Returns 0 on success, or a non-zero value on failure. 7203 */ 7204 int32_t 7205 sli_fcp_cont_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge, 7206 uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t sec_xri, uint16_t tag, 7207 uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags, 7208 uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id) 7209 { 7210 int32_t rc; 7211 7212 rc = sli_fcp_treceive64_wqe(sli4, buf, size, sgl, first_data_sge, relative_off, xfer_len, xri, tag, 7213 cq_id, xid, rpi, rnode, flags, dif, bs, csctl, app_id); 7214 if (rc == 0) { 7215 sli4_fcp_treceive64_wqe_t *trecv = buf; 7216 7217 trecv->command = SLI4_WQE_FCP_CONT_TRECEIVE64; 7218 trecv->dword5.sec_xri_tag = sec_xri; 7219 } 7220 return rc; 7221 } 7222 7223 /** 7224 * @ingroup sli_fc 7225 * @brief Write an FCP_TRSP64_WQE work queue entry. 7226 * 7227 * @param sli4 SLI context. 7228 * @param buf Destination buffer for the WQE. 7229 * @param size Buffer size, in bytes. 7230 * @param sgl DMA memory for the Scatter-Gather List. 7231 * @param rsp_len Response data length. 7232 * @param xri XRI for this exchange. 7233 * @param tag IO tag value. 7234 * @param cq_id The id of the completion queue where the WQE response is sent. 7235 * @param xid OX_ID for the exchange. 7236 * @param rpi remote node indicator (RPI) 7237 * @param rnode Destination request (i.e. remote node). 7238 * @param flags Optional attributes, including: 7239 * - ACTIVE - IO is already active 7240 * - AUTO RSP - Automatically generate a good FCP_RSP. 7241 * @param csctl value of csctl field. 7242 * @param port_owned 0/1 to indicate if the XRI is port owned (used to set XBL=0) 7243 * @param app_id value for VM application header. 7244 * 7245 * @return Returns 0 on success, or a non-zero value on failure. 7246 */ 7247 int32_t 7248 sli_fcp_trsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t rsp_len, 7249 uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, 7250 uint32_t flags, uint8_t csctl, uint8_t port_owned, uint32_t app_id) 7251 { 7252 sli4_fcp_trsp64_wqe_t *trsp = buf; 7253 sli4_fcp_128byte_wqe_t *trsp_128 = buf; 7254 7255 ocs_memset(buf, 0, size); 7256 7257 if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) { 7258 trsp->ag = TRUE; 7259 /* 7260 * The SLI-4 documentation states that the BDE is ignored when 7261 * using auto-good response, but, at least for IF_TYPE 0 devices, 7262 * this does not appear to be true. 7263 */ 7264 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) { 7265 trsp->bde.buffer_length = 12; /* byte size of RSP */ 7266 } 7267 } else { 7268 sli4_sge_t *sge = sgl->virt; 7269 7270 if (sli4->config.sgl_pre_registered || port_owned) { 7271 trsp->dbde = TRUE; 7272 } else { 7273 trsp->xbl = TRUE; 7274 } 7275 7276 trsp->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7277 trsp->bde.buffer_length = sge[0].buffer_length; 7278 trsp->bde.u.data.buffer_address_low = sge[0].buffer_address_low; 7279 trsp->bde.u.data.buffer_address_high = sge[0].buffer_address_high; 7280 7281 trsp->fcp_response_length = rsp_len; 7282 } 7283 7284 if (flags & SLI4_IO_CONTINUATION) { 7285 trsp->xc = TRUE; 7286 } 7287 7288 if (rnode->node_group) { 7289 trsp->hlm = TRUE; 7290 trsp->dword5 = rnode->fc_id & 0x00ffffff; 7291 } 7292 7293 trsp->xri_tag = xri; 7294 trsp->rpi = rpi; 7295 7296 trsp->command = SLI4_WQE_FCP_TRSP64; 7297 trsp->class = SLI4_ELS_REQUEST64_CLASS_3; 7298 7299 trsp->remote_xid = xid; 7300 trsp->request_tag = tag; 7301 trsp->dnrx = ((flags & SLI4_IO_DNRX) == 0 ? 0 : 1); 7302 trsp->len_loc = 0x1; 7303 trsp->cq_id = cq_id; 7304 trsp->cmd_type = SLI4_CMD_FCP_TRSP64_WQE; 7305 7306 /* The upper 7 bits of csctl is the priority */ 7307 if (csctl & SLI4_MASK_CCP) { 7308 trsp->ccpe = 1; 7309 trsp->ccp = (csctl & SLI4_MASK_CCP); 7310 } 7311 7312 if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trsp->eat) { 7313 trsp->app_id_valid = 1; 7314 trsp->wqes = 1; 7315 trsp_128->dw[31] = app_id; 7316 } 7317 return 0; 7318 } 7319 7320 /** 7321 * @ingroup sli_fc 7322 * @brief Write an FCP_TSEND64_WQE work queue entry. 7323 * 7324 * @param sli4 SLI context. 7325 * @param buf Destination buffer for the WQE. 7326 * @param size Buffer size, in bytes. 7327 * @param sgl DMA memory for the scatter gather list. 7328 * @param first_data_sge Index of first data sge (used if perf hints are enabled) 7329 * @param relative_off Relative offset of the IO (if any). 7330 * @param xfer_len Data transfer length. 7331 * @param xri XRI for this exchange. 7332 * @param tag IO tag value. 7333 * @param cq_id The id of the completion queue where the WQE response is sent. 7334 * @param xid OX_ID for the exchange. 7335 * @param rpi remote node indicator (RPI) 7336 * @param rnode Destination request (i.e. remote node). 7337 * @param flags Optional attributes, including: 7338 * - ACTIVE - IO is already active. 7339 * - AUTO RSP - Automatically generate a good FCP_RSP. 7340 * @param dif T10 DIF operation, or 0 to disable. 7341 * @param bs T10 DIF block size, or 0 if DIF is disabled. 7342 * @param csctl value of csctl field. 7343 * @param app_id value for VM application header. 7344 * 7345 * @return Returns 0 on success, or a non-zero value on failure. 7346 */ 7347 int32_t 7348 sli_fcp_tsend64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge, 7349 uint32_t relative_off, uint32_t xfer_len, 7350 uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, 7351 uint32_t flags, uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id) 7352 { 7353 sli4_fcp_tsend64_wqe_t *tsend = buf; 7354 sli4_fcp_128byte_wqe_t *tsend_128 = buf; 7355 sli4_sge_t *sge = NULL; 7356 7357 ocs_memset(buf, 0, size); 7358 7359 if (!sgl || !sgl->virt) { 7360 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n", 7361 sgl, sgl ? sgl->virt : NULL); 7362 return -1; 7363 } 7364 sge = sgl->virt; 7365 7366 if (sli4->config.sgl_pre_registered) { 7367 tsend->xbl = FALSE; 7368 7369 tsend->dbde = TRUE; 7370 tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7371 7372 /* TSEND64_WQE specifies first two SGE are skipped 7373 * (i.e. 3rd is valid) */ 7374 tsend->bde.buffer_length = sge[2].buffer_length; 7375 tsend->bde.u.data.buffer_address_low = sge[2].buffer_address_low; 7376 tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high; 7377 } else { 7378 tsend->xbl = TRUE; 7379 7380 /* if data is a single physical address, use a BDE */ 7381 if (!dif && (xfer_len <= sge[2].buffer_length)) { 7382 tsend->dbde = TRUE; 7383 tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7384 /* TSEND64_WQE specifies first two SGE are skipped 7385 * (i.e. 3rd is valid) */ 7386 tsend->bde.buffer_length = sge[2].buffer_length; 7387 tsend->bde.u.data.buffer_address_low = sge[2].buffer_address_low; 7388 tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high; 7389 } else { 7390 tsend->bde.bde_type = SLI4_BDE_TYPE_BLP; 7391 tsend->bde.buffer_length = sgl->size; 7392 tsend->bde.u.blp.sgl_segment_address_low = ocs_addr32_lo(sgl->phys); 7393 tsend->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys); 7394 } 7395 } 7396 7397 tsend->relative_offset = relative_off; 7398 7399 if (flags & SLI4_IO_CONTINUATION) { 7400 tsend->xc = TRUE; 7401 } 7402 tsend->xri_tag = xri; 7403 7404 tsend->rpi = rpi; 7405 7406 tsend->pu = TRUE; /* WQE uses relative offset */ 7407 7408 if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) { 7409 tsend->ar = TRUE; 7410 } 7411 7412 tsend->command = SLI4_WQE_FCP_TSEND64; 7413 tsend->class = SLI4_ELS_REQUEST64_CLASS_3; 7414 tsend->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 7415 tsend->dif = dif; 7416 tsend->bs = bs; 7417 7418 tsend->remote_xid = xid; 7419 7420 tsend->request_tag = tag; 7421 7422 tsend->len_loc = 0x2; 7423 7424 if (rnode->node_group) { 7425 tsend->hlm = TRUE; 7426 tsend->dword5 = rnode->fc_id & 0x00ffffff; 7427 } 7428 7429 tsend->cq_id = cq_id; 7430 7431 tsend->cmd_type = SLI4_CMD_FCP_TSEND64_WQE; 7432 7433 tsend->fcp_data_transmit_length = xfer_len; 7434 7435 if (sli4->config.perf_hint) { 7436 tsend->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7437 tsend->first_data_bde.buffer_length = sge[first_data_sge].buffer_length; 7438 tsend->first_data_bde.u.data.buffer_address_low = sge[first_data_sge].buffer_address_low; 7439 tsend->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high; 7440 } 7441 7442 /* The upper 7 bits of csctl is the priority */ 7443 if (csctl & SLI4_MASK_CCP) { 7444 tsend->ccpe = 1; 7445 tsend->ccp = (csctl & SLI4_MASK_CCP); 7446 } 7447 7448 if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !tsend->eat) { 7449 tsend->app_id_valid = 1; 7450 tsend->wqes = 1; 7451 tsend_128->dw[31] = app_id; 7452 } 7453 return 0; 7454 } 7455 7456 /** 7457 * @ingroup sli_fc 7458 * @brief Write a GEN_REQUEST64 work queue entry. 7459 * 7460 * @note This WQE is only used to send FC-CT commands. 7461 * 7462 * @param sli4 SLI context. 7463 * @param buf Destination buffer for the WQE. 7464 * @param size Buffer size, in bytes. 7465 * @param sgl DMA memory for the request. 7466 * @param req_len Length of request. 7467 * @param max_rsp_len Max length of response. 7468 * @param timeout Time, in seconds, before an IO times out. Zero means infinite. 7469 * @param xri XRI for this exchange. 7470 * @param tag IO tag value. 7471 * @param cq_id The id of the completion queue where the WQE response is sent. 7472 * @param rnode Destination of request (that is, the remote node). 7473 * @param r_ctl R_CTL value for sequence. 7474 * @param type TYPE value for sequence. 7475 * @param df_ctl DF_CTL value for sequence. 7476 * 7477 * @return Returns 0 on success, or a non-zero value on failure. 7478 */ 7479 int32_t 7480 sli_gen_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, 7481 uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout, 7482 uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode, 7483 uint8_t r_ctl, uint8_t type, uint8_t df_ctl) 7484 { 7485 sli4_gen_request64_wqe_t *gen = buf; 7486 sli4_sge_t *sge = NULL; 7487 7488 ocs_memset(buf, 0, size); 7489 7490 if (!sgl || !sgl->virt) { 7491 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n", 7492 sgl, sgl ? sgl->virt : NULL); 7493 return -1; 7494 } 7495 sge = sgl->virt; 7496 7497 if (sli4->config.sgl_pre_registered) { 7498 gen->xbl = FALSE; 7499 7500 gen->dbde = TRUE; 7501 gen->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7502 7503 gen->bde.buffer_length = req_len; 7504 gen->bde.u.data.buffer_address_low = sge[0].buffer_address_low; 7505 gen->bde.u.data.buffer_address_high = sge[0].buffer_address_high; 7506 } else { 7507 gen->xbl = TRUE; 7508 7509 gen->bde.bde_type = SLI4_BDE_TYPE_BLP; 7510 7511 gen->bde.buffer_length = 2 * sizeof(sli4_sge_t); 7512 gen->bde.u.blp.sgl_segment_address_low = ocs_addr32_lo(sgl->phys); 7513 gen->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys); 7514 } 7515 7516 gen->request_payload_length = req_len; 7517 gen->max_response_payload_length = max_rsp_len; 7518 7519 gen->df_ctl = df_ctl; 7520 gen->type = type; 7521 gen->r_ctl = r_ctl; 7522 7523 gen->xri_tag = xri; 7524 7525 gen->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 7526 gen->context_tag = rnode->indicator; 7527 7528 gen->class = SLI4_ELS_REQUEST64_CLASS_3; 7529 7530 gen->command = SLI4_WQE_GEN_REQUEST64; 7531 7532 gen->timer = timeout; 7533 7534 gen->request_tag = tag; 7535 7536 gen->iod = SLI4_ELS_REQUEST64_DIR_READ; 7537 7538 gen->qosd = TRUE; 7539 7540 if (rnode->node_group) { 7541 gen->hlm = TRUE; 7542 gen->remote_n_port_id = rnode->fc_id & 0x00ffffff; 7543 } 7544 7545 gen->cmd_type = SLI4_CMD_GEN_REQUEST64_WQE; 7546 7547 gen->cq_id = cq_id; 7548 7549 return 0; 7550 } 7551 7552 /** 7553 * @ingroup sli_fc 7554 * @brief Write a SEND_FRAME work queue entry 7555 * 7556 * @param sli4 SLI context. 7557 * @param buf Destination buffer for the WQE. 7558 * @param size Buffer size, in bytes. 7559 * @param sof Start of frame value 7560 * @param eof End of frame value 7561 * @param hdr Pointer to FC header data 7562 * @param payload DMA memory for the payload. 7563 * @param req_len Length of payload. 7564 * @param timeout Time, in seconds, before an IO times out. Zero means infinite. 7565 * @param xri XRI for this exchange. 7566 * @param req_tag IO tag value. 7567 * 7568 * @return Returns 0 on success, or a non-zero value on failure. 7569 */ 7570 int32_t 7571 sli_send_frame_wqe(sli4_t *sli4, void *buf, size_t size, uint8_t sof, uint8_t eof, uint32_t *hdr, 7572 ocs_dma_t *payload, uint32_t req_len, uint8_t timeout, 7573 uint16_t xri, uint16_t req_tag) 7574 { 7575 sli4_send_frame_wqe_t *sf = buf; 7576 7577 ocs_memset(buf, 0, size); 7578 7579 sf->dbde = TRUE; 7580 sf->bde.buffer_length = req_len; 7581 sf->bde.u.data.buffer_address_low = ocs_addr32_lo(payload->phys); 7582 sf->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys); 7583 7584 /* Copy FC header */ 7585 sf->fc_header_0_1[0] = hdr[0]; 7586 sf->fc_header_0_1[1] = hdr[1]; 7587 sf->fc_header_2_5[0] = hdr[2]; 7588 sf->fc_header_2_5[1] = hdr[3]; 7589 sf->fc_header_2_5[2] = hdr[4]; 7590 sf->fc_header_2_5[3] = hdr[5]; 7591 7592 sf->frame_length = req_len; 7593 7594 sf->xri_tag = xri; 7595 sf->pu = 0; 7596 sf->context_tag = 0; 7597 7598 sf->ct = 0; 7599 sf->command = SLI4_WQE_SEND_FRAME; 7600 sf->class = SLI4_ELS_REQUEST64_CLASS_3; 7601 sf->timer = timeout; 7602 7603 sf->request_tag = req_tag; 7604 sf->eof = eof; 7605 sf->sof = sof; 7606 7607 sf->qosd = 0; 7608 sf->lenloc = 1; 7609 sf->xc = 0; 7610 7611 sf->xbl = 1; 7612 7613 sf->cmd_type = SLI4_CMD_SEND_FRAME_WQE; 7614 sf->cq_id = 0xffff; 7615 7616 return 0; 7617 } 7618 7619 /** 7620 * @ingroup sli_fc 7621 * @brief Write a XMIT_SEQUENCE64 work queue entry. 7622 * 7623 * This WQE is used to send FC-CT response frames. 7624 * 7625 * @note This API implements a restricted use for this WQE, a TODO: would 7626 * include passing in sequence initiative, and full SGL's 7627 * 7628 * @param sli4 SLI context. 7629 * @param buf Destination buffer for the WQE. 7630 * @param size Buffer size, in bytes. 7631 * @param payload DMA memory for the request. 7632 * @param payload_len Length of request. 7633 * @param timeout Time, in seconds, before an IO times out. Zero means infinite. 7634 * @param ox_id originator exchange ID 7635 * @param xri XRI for this exchange. 7636 * @param tag IO tag value. 7637 * @param rnode Destination of request (that is, the remote node). 7638 * @param r_ctl R_CTL value for sequence. 7639 * @param type TYPE value for sequence. 7640 * @param df_ctl DF_CTL value for sequence. 7641 * 7642 * @return Returns 0 on success, or a non-zero value on failure. 7643 */ 7644 int32_t 7645 sli_xmit_sequence64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload, 7646 uint32_t payload_len, uint8_t timeout, uint16_t ox_id, 7647 uint16_t xri, uint16_t tag, ocs_remote_node_t *rnode, 7648 uint8_t r_ctl, uint8_t type, uint8_t df_ctl) 7649 { 7650 sli4_xmit_sequence64_wqe_t *xmit = buf; 7651 7652 ocs_memset(buf, 0, size); 7653 7654 if ((payload == NULL) || (payload->virt == NULL)) { 7655 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n", 7656 payload, payload ? payload->virt : NULL); 7657 return -1; 7658 } 7659 7660 if (sli4->config.sgl_pre_registered) { 7661 xmit->dbde = TRUE; 7662 } else { 7663 xmit->xbl = TRUE; 7664 } 7665 7666 xmit->bde.bde_type = SLI4_BDE_TYPE_BDE_64; 7667 xmit->bde.buffer_length = payload_len; 7668 xmit->bde.u.data.buffer_address_low = ocs_addr32_lo(payload->phys); 7669 xmit->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys); 7670 xmit->sequence_payload_len = payload_len; 7671 7672 xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff; 7673 7674 xmit->relative_offset = 0; 7675 7676 xmit->si = 0; /* sequence initiative - this matches what is seen from 7677 * FC switches in response to FCGS commands */ 7678 xmit->ft = 0; /* force transmit */ 7679 xmit->xo = 0; /* exchange responder */ 7680 xmit->ls = 1; /* last in seqence */ 7681 xmit->df_ctl = df_ctl; 7682 xmit->type = type; 7683 xmit->r_ctl = r_ctl; 7684 7685 xmit->xri_tag = xri; 7686 xmit->context_tag = rnode->indicator; 7687 7688 xmit->dif = 0; 7689 xmit->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 7690 xmit->bs = 0; 7691 7692 xmit->command = SLI4_WQE_XMIT_SEQUENCE64; 7693 xmit->class = SLI4_ELS_REQUEST64_CLASS_3; 7694 xmit->pu = 0; 7695 xmit->timer = timeout; 7696 7697 xmit->abort_tag = 0; 7698 xmit->request_tag = tag; 7699 xmit->remote_xid = ox_id; 7700 7701 xmit->iod = SLI4_ELS_REQUEST64_DIR_READ; 7702 7703 if (rnode->node_group) { 7704 xmit->hlm = TRUE; 7705 xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff; 7706 } 7707 7708 xmit->cmd_type = SLI4_CMD_XMIT_SEQUENCE64_WQE; 7709 7710 xmit->len_loc = 2; 7711 7712 xmit->cq_id = 0xFFFF; 7713 7714 return 0; 7715 } 7716 7717 /** 7718 * @ingroup sli_fc 7719 * @brief Write a REQUEUE_XRI_WQE work queue entry. 7720 * 7721 * @param sli4 SLI context. 7722 * @param buf Destination buffer for the WQE. 7723 * @param size Buffer size, in bytes. 7724 * @param xri XRI for this exchange. 7725 * @param tag IO tag value. 7726 * @param cq_id The id of the completion queue where the WQE response is sent. 7727 * 7728 * @return Returns 0 on success, or a non-zero value on failure. 7729 */ 7730 int32_t 7731 sli_requeue_xri_wqe(sli4_t *sli4, void *buf, size_t size, uint16_t xri, uint16_t tag, uint16_t cq_id) 7732 { 7733 sli4_requeue_xri_wqe_t *requeue = buf; 7734 7735 ocs_memset(buf, 0, size); 7736 7737 requeue->command = SLI4_WQE_REQUEUE_XRI; 7738 requeue->xri_tag = xri; 7739 requeue->request_tag = tag; 7740 requeue->xc = 1; 7741 requeue->qosd = 1; 7742 requeue->cq_id = cq_id; 7743 requeue->cmd_type = SLI4_CMD_REQUEUE_XRI_WQE; 7744 return 0; 7745 } 7746 7747 int32_t 7748 sli_xmit_bcast64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload, 7749 uint32_t payload_len, uint8_t timeout, uint16_t xri, uint16_t tag, 7750 uint16_t cq_id, ocs_remote_node_t *rnode, 7751 uint8_t r_ctl, uint8_t type, uint8_t df_ctl) 7752 { 7753 sli4_xmit_bcast64_wqe_t *bcast = buf; 7754 7755 /* Command requires a temporary RPI (i.e. unused remote node) */ 7756 if (rnode->attached) { 7757 ocs_log_test(sli4->os, "remote node %d in use\n", rnode->indicator); 7758 return -1; 7759 } 7760 7761 ocs_memset(buf, 0, size); 7762 7763 bcast->dbde = TRUE; 7764 bcast->sequence_payload.bde_type = SLI4_BDE_TYPE_BDE_64; 7765 bcast->sequence_payload.buffer_length = payload_len; 7766 bcast->sequence_payload.u.data.buffer_address_low = ocs_addr32_lo(payload->phys); 7767 bcast->sequence_payload.u.data.buffer_address_high = ocs_addr32_hi(payload->phys); 7768 7769 bcast->sequence_payload_length = payload_len; 7770 7771 bcast->df_ctl = df_ctl; 7772 bcast->type = type; 7773 bcast->r_ctl = r_ctl; 7774 7775 bcast->xri_tag = xri; 7776 7777 bcast->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 7778 bcast->context_tag = rnode->sport->indicator; 7779 7780 bcast->class = SLI4_ELS_REQUEST64_CLASS_3; 7781 7782 bcast->command = SLI4_WQE_XMIT_BCAST64; 7783 7784 bcast->timer = timeout; 7785 7786 bcast->request_tag = tag; 7787 7788 bcast->temporary_rpi = rnode->indicator; 7789 7790 bcast->len_loc = 0x1; 7791 7792 bcast->iod = SLI4_ELS_REQUEST64_DIR_WRITE; 7793 7794 bcast->cmd_type = SLI4_CMD_XMIT_BCAST64_WQE; 7795 7796 bcast->cq_id = cq_id; 7797 7798 return 0; 7799 } 7800 7801 /** 7802 * @ingroup sli_fc 7803 * @brief Write an XMIT_BLS_RSP64_WQE work queue entry. 7804 * 7805 * @param sli4 SLI context. 7806 * @param buf Destination buffer for the WQE. 7807 * @param size Buffer size, in bytes. 7808 * @param payload Contents of the BLS payload to be sent. 7809 * @param xri XRI for this exchange. 7810 * @param tag IO tag value. 7811 * @param cq_id The id of the completion queue where the WQE response is sent. 7812 * @param rnode Destination of request (that is, the remote node). 7813 * @param s_id Source ID to use in the response. If UINT32_MAX, use SLI Port's ID. 7814 * 7815 * @return Returns 0 on success, or a non-zero value on failure. 7816 */ 7817 int32_t 7818 sli_xmit_bls_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, sli_bls_payload_t *payload, 7819 uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode, uint32_t s_id) 7820 { 7821 sli4_xmit_bls_rsp_wqe_t *bls = buf; 7822 7823 /* 7824 * Callers can either specify RPI or S_ID, but not both 7825 */ 7826 if (rnode->attached && (s_id != UINT32_MAX)) { 7827 ocs_log_test(sli4->os, "S_ID specified for attached remote node %d\n", 7828 rnode->indicator); 7829 return -1; 7830 } 7831 7832 ocs_memset(buf, 0, size); 7833 7834 if (SLI_BLS_ACC == payload->type) { 7835 bls->payload_word0 = (payload->u.acc.seq_id_last << 16) | 7836 (payload->u.acc.seq_id_validity << 24); 7837 bls->high_seq_cnt = payload->u.acc.high_seq_cnt; 7838 bls->low_seq_cnt = payload->u.acc.low_seq_cnt; 7839 } else if (SLI_BLS_RJT == payload->type) { 7840 bls->payload_word0 = *((uint32_t *)&payload->u.rjt); 7841 bls->ar = TRUE; 7842 } else { 7843 ocs_log_test(sli4->os, "bad BLS type %#x\n", 7844 payload->type); 7845 return -1; 7846 } 7847 7848 bls->ox_id = payload->ox_id; 7849 bls->rx_id = payload->rx_id; 7850 7851 if (rnode->attached) { 7852 bls->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 7853 bls->context_tag = rnode->indicator; 7854 } else { 7855 bls->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 7856 bls->context_tag = rnode->sport->indicator; 7857 7858 if (UINT32_MAX != s_id) { 7859 bls->local_n_port_id = s_id & 0x00ffffff; 7860 } else { 7861 bls->local_n_port_id = rnode->sport->fc_id & 0x00ffffff; 7862 } 7863 bls->remote_id = rnode->fc_id & 0x00ffffff; 7864 7865 bls->temporary_rpi = rnode->indicator; 7866 } 7867 7868 bls->xri_tag = xri; 7869 7870 bls->class = SLI4_ELS_REQUEST64_CLASS_3; 7871 7872 bls->command = SLI4_WQE_XMIT_BLS_RSP; 7873 7874 bls->request_tag = tag; 7875 7876 bls->qosd = TRUE; 7877 7878 if (rnode->node_group) { 7879 bls->hlm = TRUE; 7880 bls->remote_id = rnode->fc_id & 0x00ffffff; 7881 } 7882 7883 bls->cq_id = cq_id; 7884 7885 bls->cmd_type = SLI4_CMD_XMIT_BLS_RSP64_WQE; 7886 7887 return 0; 7888 } 7889 7890 /** 7891 * @ingroup sli_fc 7892 * @brief Write a XMIT_ELS_RSP64_WQE work queue entry. 7893 * 7894 * @param sli4 SLI context. 7895 * @param buf Destination buffer for the WQE. 7896 * @param size Buffer size, in bytes. 7897 * @param rsp DMA memory for the ELS response. 7898 * @param rsp_len Length of ELS response, in bytes. 7899 * @param xri XRI for this exchange. 7900 * @param tag IO tag value. 7901 * @param cq_id The id of the completion queue where the WQE response is sent. 7902 * @param ox_id OX_ID of the exchange containing the request. 7903 * @param rnode Destination of the ELS response (that is, the remote node). 7904 * @param flags Optional attributes, including: 7905 * - SLI4_IO_CONTINUATION - IO is already active. 7906 * @param s_id S_ID used for special responses. 7907 * 7908 * @return Returns 0 on success, or a non-zero value on failure. 7909 */ 7910 int32_t 7911 sli_xmit_els_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *rsp, 7912 uint32_t rsp_len, uint16_t xri, uint16_t tag, uint16_t cq_id, 7913 uint16_t ox_id, ocs_remote_node_t *rnode, uint32_t flags, uint32_t s_id) 7914 { 7915 sli4_xmit_els_rsp64_wqe_t *els = buf; 7916 7917 ocs_memset(buf, 0, size); 7918 7919 if (sli4->config.sgl_pre_registered) { 7920 els->dbde = TRUE; 7921 } else { 7922 els->xbl = TRUE; 7923 } 7924 7925 els->els_response_payload.bde_type = SLI4_BDE_TYPE_BDE_64; 7926 els->els_response_payload.buffer_length = rsp_len; 7927 els->els_response_payload.u.data.buffer_address_low = ocs_addr32_lo(rsp->phys); 7928 els->els_response_payload.u.data.buffer_address_high = ocs_addr32_hi(rsp->phys); 7929 7930 els->els_response_payload_length = rsp_len; 7931 7932 els->xri_tag = xri; 7933 7934 els->class = SLI4_ELS_REQUEST64_CLASS_3; 7935 7936 els->command = SLI4_WQE_ELS_RSP64; 7937 7938 els->request_tag = tag; 7939 7940 els->ox_id = ox_id; 7941 7942 els->iod = SLI4_ELS_REQUEST64_DIR_WRITE; 7943 7944 els->qosd = TRUE; 7945 7946 if (flags & SLI4_IO_CONTINUATION) { 7947 els->xc = TRUE; 7948 } 7949 7950 if (rnode->attached) { 7951 els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI; 7952 els->context_tag = rnode->indicator; 7953 } else { 7954 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI; 7955 els->context_tag = rnode->sport->indicator; 7956 els->remote_id = rnode->fc_id & 0x00ffffff; 7957 els->temporary_rpi = rnode->indicator; 7958 if (UINT32_MAX != s_id) { 7959 els->sp = TRUE; 7960 els->s_id = s_id & 0x00ffffff; 7961 } 7962 } 7963 7964 if (rnode->node_group) { 7965 els->hlm = TRUE; 7966 els->remote_id = rnode->fc_id & 0x00ffffff; 7967 } 7968 7969 els->cmd_type = SLI4_ELS_REQUEST64_CMD_GEN; 7970 7971 els->cq_id = cq_id; 7972 7973 return 0; 7974 } 7975 7976 /** 7977 * @ingroup sli_fc 7978 * @brief Process an asynchronous Link State event entry. 7979 * 7980 * @par Description 7981 * Parses Asynchronous Completion Queue Entry (ACQE), 7982 * creates an abstracted event, and calls registered callback functions. 7983 * 7984 * @param sli4 SLI context. 7985 * @param acqe Pointer to the ACQE. 7986 * 7987 * @return Returns 0 on success, or a non-zero value on failure. 7988 */ 7989 int32_t 7990 sli_fc_process_link_state(sli4_t *sli4, void *acqe) 7991 { 7992 sli4_link_state_t *link_state = acqe; 7993 sli4_link_event_t event = { 0 }; 7994 int32_t rc = 0; 7995 7996 if (!sli4->link) { 7997 /* bail if there is no callback */ 7998 return 0; 7999 } 8000 8001 if (SLI4_LINK_TYPE_ETHERNET == link_state->link_type) { 8002 event.topology = SLI_LINK_TOPO_NPORT; 8003 event.medium = SLI_LINK_MEDIUM_ETHERNET; 8004 } else { 8005 /* TODO is this supported for anything other than FCoE? */ 8006 ocs_log_test(sli4->os, "unsupported link type %#x\n", 8007 link_state->link_type); 8008 event.topology = SLI_LINK_TOPO_MAX; 8009 event.medium = SLI_LINK_MEDIUM_MAX; 8010 rc = -1; 8011 } 8012 8013 switch (link_state->port_link_status) { 8014 case SLI4_PORT_LINK_STATUS_PHYSICAL_DOWN: 8015 case SLI4_PORT_LINK_STATUS_LOGICAL_DOWN: 8016 event.status = SLI_LINK_STATUS_DOWN; 8017 break; 8018 case SLI4_PORT_LINK_STATUS_PHYSICAL_UP: 8019 case SLI4_PORT_LINK_STATUS_LOGICAL_UP: 8020 event.status = SLI_LINK_STATUS_UP; 8021 break; 8022 default: 8023 ocs_log_test(sli4->os, "unsupported link status %#x\n", 8024 link_state->port_link_status); 8025 event.status = SLI_LINK_STATUS_MAX; 8026 rc = -1; 8027 } 8028 8029 switch (link_state->port_speed) { 8030 case 0: 8031 event.speed = 0; 8032 break; 8033 case 1: 8034 event.speed = 10; 8035 break; 8036 case 2: 8037 event.speed = 100; 8038 break; 8039 case 3: 8040 event.speed = 1000; 8041 break; 8042 case 4: 8043 event.speed = 10000; 8044 break; 8045 case 5: 8046 event.speed = 20000; 8047 break; 8048 case 6: 8049 event.speed = 25000; 8050 break; 8051 case 7: 8052 event.speed = 40000; 8053 break; 8054 case 8: 8055 event.speed = 100000; 8056 break; 8057 default: 8058 ocs_log_test(sli4->os, "unsupported port_speed %#x\n", 8059 link_state->port_speed); 8060 rc = -1; 8061 } 8062 8063 sli4->link(sli4->link_arg, (void *)&event); 8064 8065 return rc; 8066 } 8067 8068 /** 8069 * @ingroup sli_fc 8070 * @brief Process an asynchronous Link Attention event entry. 8071 * 8072 * @par Description 8073 * Parses Asynchronous Completion Queue Entry (ACQE), 8074 * creates an abstracted event, and calls the registered callback functions. 8075 * 8076 * @param sli4 SLI context. 8077 * @param acqe Pointer to the ACQE. 8078 * 8079 * @todo XXX all events return LINK_UP. 8080 * 8081 * @return Returns 0 on success, or a non-zero value on failure. 8082 */ 8083 int32_t 8084 sli_fc_process_link_attention(sli4_t *sli4, void *acqe) 8085 { 8086 sli4_link_attention_t *link_attn = acqe; 8087 sli4_link_event_t event = { 0 }; 8088 8089 ocs_log_debug(sli4->os, "link_number=%d attn_type=%#x topology=%#x port_speed=%#x " 8090 "port_fault=%#x shared_link_status=%#x logical_link_speed=%#x " 8091 "event_tag=%#x\n", link_attn->link_number, link_attn->attn_type, 8092 link_attn->topology, link_attn->port_speed, link_attn->port_fault, 8093 link_attn->shared_link_status, link_attn->logical_link_speed, 8094 link_attn->event_tag); 8095 8096 if (!sli4->link) { 8097 return 0; 8098 } 8099 8100 event.medium = SLI_LINK_MEDIUM_FC; 8101 8102 switch (link_attn->attn_type) { 8103 case SLI4_LINK_ATTN_TYPE_LINK_UP: 8104 event.status = SLI_LINK_STATUS_UP; 8105 break; 8106 case SLI4_LINK_ATTN_TYPE_LINK_DOWN: 8107 event.status = SLI_LINK_STATUS_DOWN; 8108 break; 8109 case SLI4_LINK_ATTN_TYPE_NO_HARD_ALPA: 8110 ocs_log_debug(sli4->os, "attn_type: no hard alpa\n"); 8111 event.status = SLI_LINK_STATUS_NO_ALPA; 8112 break; 8113 default: 8114 ocs_log_test(sli4->os, "attn_type: unknown\n"); 8115 break; 8116 } 8117 8118 switch (link_attn->event_type) { 8119 case SLI4_FC_EVENT_LINK_ATTENTION: 8120 break; 8121 case SLI4_FC_EVENT_SHARED_LINK_ATTENTION: 8122 ocs_log_debug(sli4->os, "event_type: FC shared link event \n"); 8123 break; 8124 default: 8125 ocs_log_test(sli4->os, "event_type: unknown\n"); 8126 break; 8127 } 8128 8129 switch (link_attn->topology) { 8130 case SLI4_LINK_ATTN_P2P: 8131 event.topology = SLI_LINK_TOPO_NPORT; 8132 break; 8133 case SLI4_LINK_ATTN_FC_AL: 8134 event.topology = SLI_LINK_TOPO_LOOP; 8135 break; 8136 case SLI4_LINK_ATTN_INTERNAL_LOOPBACK: 8137 ocs_log_debug(sli4->os, "topology Internal loopback\n"); 8138 event.topology = SLI_LINK_TOPO_LOOPBACK_INTERNAL; 8139 break; 8140 case SLI4_LINK_ATTN_SERDES_LOOPBACK: 8141 ocs_log_debug(sli4->os, "topology serdes loopback\n"); 8142 event.topology = SLI_LINK_TOPO_LOOPBACK_EXTERNAL; 8143 break; 8144 default: 8145 ocs_log_test(sli4->os, "topology: unknown\n"); 8146 break; 8147 } 8148 8149 event.speed = link_attn->port_speed * 1000; 8150 8151 sli4->link(sli4->link_arg, (void *)&event); 8152 8153 return 0; 8154 } 8155 8156 /** 8157 * @ingroup sli_fc 8158 * @brief Parse an FC/FCoE work queue CQ entry. 8159 * 8160 * @param sli4 SLI context. 8161 * @param cq CQ to process. 8162 * @param cqe Pointer to the CQ entry. 8163 * @param etype CQ event type. 8164 * @param r_id Resource ID associated with this completion message (such as the IO tag). 8165 * 8166 * @return Returns 0 on success, or a non-zero value on failure. 8167 */ 8168 int32_t 8169 sli_fc_cqe_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype, 8170 uint16_t *r_id) 8171 { 8172 uint8_t code = cqe[SLI4_CQE_CODE_OFFSET]; 8173 int32_t rc = -1; 8174 8175 switch (code) { 8176 case SLI4_CQE_CODE_WORK_REQUEST_COMPLETION: 8177 { 8178 sli4_fc_wcqe_t *wcqe = (void *)cqe; 8179 8180 *etype = SLI_QENTRY_WQ; 8181 *r_id = wcqe->request_tag; 8182 rc = wcqe->status; 8183 8184 /* Flag errors except for FCP_RSP_FAILURE */ 8185 if (rc && (rc != SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE)) { 8186 ocs_log_test(sli4->os, "WCQE: status=%#x hw_status=%#x tag=%#x w1=%#x w2=%#x xb=%d\n", 8187 wcqe->status, wcqe->hw_status, 8188 wcqe->request_tag, wcqe->wqe_specific_1, 8189 wcqe->wqe_specific_2, wcqe->xb); 8190 ocs_log_test(sli4->os, " %08X %08X %08X %08X\n", ((uint32_t*) cqe)[0], ((uint32_t*) cqe)[1], 8191 ((uint32_t*) cqe)[2], ((uint32_t*) cqe)[3]); 8192 } 8193 8194 /* TODO: need to pass additional status back out of here as well 8195 * as status (could overload rc as status/addlstatus are only 8 bits each) 8196 */ 8197 8198 break; 8199 } 8200 case SLI4_CQE_CODE_RQ_ASYNC: 8201 { 8202 sli4_fc_async_rcqe_t *rcqe = (void *)cqe; 8203 8204 *etype = SLI_QENTRY_RQ; 8205 *r_id = rcqe->rq_id; 8206 rc = rcqe->status; 8207 break; 8208 } 8209 case SLI4_CQE_CODE_RQ_ASYNC_V1: 8210 { 8211 sli4_fc_async_rcqe_v1_t *rcqe = (void *)cqe; 8212 8213 *etype = SLI_QENTRY_RQ; 8214 *r_id = rcqe->rq_id; 8215 rc = rcqe->status; 8216 break; 8217 } 8218 case SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD: 8219 { 8220 sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe; 8221 8222 *etype = SLI_QENTRY_OPT_WRITE_CMD; 8223 *r_id = optcqe->rq_id; 8224 rc = optcqe->status; 8225 break; 8226 } 8227 case SLI4_CQE_CODE_OPTIMIZED_WRITE_DATA: 8228 { 8229 sli4_fc_optimized_write_data_cqe_t *dcqe = (void *)cqe; 8230 8231 *etype = SLI_QENTRY_OPT_WRITE_DATA; 8232 *r_id = dcqe->xri; 8233 rc = dcqe->status; 8234 8235 /* Flag errors */ 8236 if (rc != SLI4_FC_WCQE_STATUS_SUCCESS) { 8237 ocs_log_test(sli4->os, "Optimized DATA CQE: status=%#x hw_status=%#x xri=%#x dpl=%#x w3=%#x xb=%d\n", 8238 dcqe->status, dcqe->hw_status, 8239 dcqe->xri, dcqe->total_data_placed, 8240 ((uint32_t*) cqe)[3], dcqe->xb); 8241 } 8242 break; 8243 } 8244 case SLI4_CQE_CODE_RQ_COALESCING: 8245 { 8246 sli4_fc_coalescing_rcqe_t *rcqe = (void *)cqe; 8247 8248 *etype = SLI_QENTRY_RQ; 8249 *r_id = rcqe->rq_id; 8250 rc = rcqe->status; 8251 break; 8252 } 8253 case SLI4_CQE_CODE_XRI_ABORTED: 8254 { 8255 sli4_fc_xri_aborted_cqe_t *xa = (void *)cqe; 8256 8257 *etype = SLI_QENTRY_XABT; 8258 *r_id = xa->xri; 8259 rc = 0; 8260 break; 8261 } 8262 case SLI4_CQE_CODE_RELEASE_WQE: { 8263 sli4_fc_wqec_t *wqec = (void*) cqe; 8264 8265 *etype = SLI_QENTRY_WQ_RELEASE; 8266 *r_id = wqec->wq_id; 8267 rc = 0; 8268 break; 8269 } 8270 default: 8271 ocs_log_test(sli4->os, "CQE completion code %d not handled\n", code); 8272 *etype = SLI_QENTRY_MAX; 8273 *r_id = UINT16_MAX; 8274 } 8275 8276 return rc; 8277 } 8278 8279 /** 8280 * @ingroup sli_fc 8281 * @brief Return the ELS/CT response length. 8282 * 8283 * @param sli4 SLI context. 8284 * @param cqe Pointer to the CQ entry. 8285 * 8286 * @return Returns the length, in bytes. 8287 */ 8288 uint32_t 8289 sli_fc_response_length(sli4_t *sli4, uint8_t *cqe) 8290 { 8291 sli4_fc_wcqe_t *wcqe = (void *)cqe; 8292 8293 return wcqe->wqe_specific_1; 8294 } 8295 8296 /** 8297 * @ingroup sli_fc 8298 * @brief Return the FCP IO length. 8299 * 8300 * @param sli4 SLI context. 8301 * @param cqe Pointer to the CQ entry. 8302 * 8303 * @return Returns the length, in bytes. 8304 */ 8305 uint32_t 8306 sli_fc_io_length(sli4_t *sli4, uint8_t *cqe) 8307 { 8308 sli4_fc_wcqe_t *wcqe = (void *)cqe; 8309 8310 return wcqe->wqe_specific_1; 8311 } 8312 8313 /** 8314 * @ingroup sli_fc 8315 * @brief Retrieve the D_ID from the completion. 8316 * 8317 * @param sli4 SLI context. 8318 * @param cqe Pointer to the CQ entry. 8319 * @param d_id Pointer where the D_ID is written. 8320 * 8321 * @return Returns 0 on success, or a non-zero value on failure. 8322 */ 8323 int32_t 8324 sli_fc_els_did(sli4_t *sli4, uint8_t *cqe, uint32_t *d_id) 8325 { 8326 sli4_fc_wcqe_t *wcqe = (void *)cqe; 8327 8328 *d_id = 0; 8329 8330 if (wcqe->status) { 8331 return -1; 8332 } else { 8333 *d_id = wcqe->wqe_specific_2 & 0x00ffffff; 8334 return 0; 8335 } 8336 } 8337 8338 uint32_t 8339 sli_fc_ext_status(sli4_t *sli4, uint8_t *cqe) 8340 { 8341 sli4_fc_wcqe_t *wcqe = (void *)cqe; 8342 uint32_t mask; 8343 8344 switch (wcqe->status) { 8345 case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE: 8346 mask = UINT32_MAX; 8347 break; 8348 case SLI4_FC_WCQE_STATUS_LOCAL_REJECT: 8349 case SLI4_FC_WCQE_STATUS_CMD_REJECT: 8350 mask = 0xff; 8351 break; 8352 case SLI4_FC_WCQE_STATUS_NPORT_RJT: 8353 case SLI4_FC_WCQE_STATUS_FABRIC_RJT: 8354 case SLI4_FC_WCQE_STATUS_NPORT_BSY: 8355 case SLI4_FC_WCQE_STATUS_FABRIC_BSY: 8356 case SLI4_FC_WCQE_STATUS_LS_RJT: 8357 mask = UINT32_MAX; 8358 break; 8359 case SLI4_FC_WCQE_STATUS_DI_ERROR: 8360 mask = UINT32_MAX; 8361 break; 8362 default: 8363 mask = 0; 8364 } 8365 8366 return wcqe->wqe_specific_2 & mask; 8367 } 8368 8369 /** 8370 * @ingroup sli_fc 8371 * @brief Retrieve the RQ index from the completion. 8372 * 8373 * @param sli4 SLI context. 8374 * @param cqe Pointer to the CQ entry. 8375 * @param rq_id Pointer where the rq_id is written. 8376 * @param index Pointer where the index is written. 8377 * 8378 * @return Returns 0 on success, or a non-zero value on failure. 8379 */ 8380 int32_t 8381 sli_fc_rqe_rqid_and_index(sli4_t *sli4, uint8_t *cqe, uint16_t *rq_id, uint32_t *index) 8382 { 8383 sli4_fc_async_rcqe_t *rcqe = (void *)cqe; 8384 sli4_fc_async_rcqe_v1_t *rcqe_v1 = (void *)cqe; 8385 int32_t rc = -1; 8386 uint8_t code = 0; 8387 8388 *rq_id = 0; 8389 *index = UINT32_MAX; 8390 8391 code = cqe[SLI4_CQE_CODE_OFFSET]; 8392 8393 if (code == SLI4_CQE_CODE_RQ_ASYNC) { 8394 *rq_id = rcqe->rq_id; 8395 if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe->status) { 8396 *index = rcqe->rq_element_index; 8397 rc = 0; 8398 } else { 8399 *index = rcqe->rq_element_index; 8400 rc = rcqe->status; 8401 ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n", 8402 rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id, 8403 rcqe->rq_element_index, rcqe->payload_data_placement_length, rcqe->sof_byte, 8404 rcqe->eof_byte, rcqe->header_data_placement_length); 8405 } 8406 } else if (code == SLI4_CQE_CODE_RQ_ASYNC_V1) { 8407 *rq_id = rcqe_v1->rq_id; 8408 if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe_v1->status) { 8409 *index = rcqe_v1->rq_element_index; 8410 rc = 0; 8411 } else { 8412 *index = rcqe_v1->rq_element_index; 8413 rc = rcqe_v1->status; 8414 ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n", 8415 rcqe_v1->status, sli_fc_get_status_string(rcqe_v1->status), 8416 rcqe_v1->rq_id, rcqe_v1->rq_element_index, 8417 rcqe_v1->payload_data_placement_length, rcqe_v1->sof_byte, 8418 rcqe_v1->eof_byte, rcqe_v1->header_data_placement_length); 8419 } 8420 } else if (code == SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD) { 8421 sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe; 8422 8423 *rq_id = optcqe->rq_id; 8424 if (SLI4_FC_ASYNC_RQ_SUCCESS == optcqe->status) { 8425 *index = optcqe->rq_element_index; 8426 rc = 0; 8427 } else { 8428 *index = optcqe->rq_element_index; 8429 rc = optcqe->status; 8430 ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x hdpl=%x oox=%d agxr=%d xri=0x%x rpi=0x%x\n", 8431 optcqe->status, sli_fc_get_status_string(optcqe->status), optcqe->rq_id, 8432 optcqe->rq_element_index, optcqe->payload_data_placement_length, 8433 optcqe->header_data_placement_length, optcqe->oox, optcqe->agxr, optcqe->xri, 8434 optcqe->rpi); 8435 } 8436 } else if (code == SLI4_CQE_CODE_RQ_COALESCING) { 8437 sli4_fc_coalescing_rcqe_t *rcqe = (void *)cqe; 8438 8439 *rq_id = rcqe->rq_id; 8440 if (SLI4_FC_COALESCE_RQ_SUCCESS == rcqe->status) { 8441 *index = rcqe->rq_element_index; 8442 rc = 0; 8443 } else { 8444 *index = UINT32_MAX; 8445 rc = rcqe->status; 8446 8447 ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x rq_id=%#x sdpl=%x\n", 8448 rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id, 8449 rcqe->rq_element_index, rcqe->rq_id, rcqe->sequence_reporting_placement_length); 8450 } 8451 } else { 8452 *index = UINT32_MAX; 8453 8454 rc = rcqe->status; 8455 8456 ocs_log_debug(sli4->os, "status=%02x rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n", 8457 rcqe->status, rcqe->rq_id, rcqe->rq_element_index, rcqe->payload_data_placement_length, 8458 rcqe->sof_byte, rcqe->eof_byte, rcqe->header_data_placement_length); 8459 } 8460 8461 return rc; 8462 } 8463 8464 /** 8465 * @ingroup sli_fc 8466 * @brief Process an asynchronous FCoE event entry. 8467 * 8468 * @par Description 8469 * Parses Asynchronous Completion Queue Entry (ACQE), 8470 * creates an abstracted event, and calls the registered callback functions. 8471 * 8472 * @param sli4 SLI context. 8473 * @param acqe Pointer to the ACQE. 8474 * 8475 * @return Returns 0 on success, or a non-zero value on failure. 8476 */ 8477 int32_t 8478 sli_fc_process_fcoe(sli4_t *sli4, void *acqe) 8479 { 8480 sli4_fcoe_fip_t *fcoe = acqe; 8481 sli4_fip_event_t event = { 0 }; 8482 uint32_t mask = UINT32_MAX; 8483 8484 ocs_log_debug(sli4->os, "ACQE FCoE FIP type=%02x count=%d tag=%#x\n", 8485 fcoe->event_type, 8486 fcoe->fcf_count, 8487 fcoe->event_tag); 8488 8489 if (!sli4->fip) { 8490 return 0; 8491 } 8492 8493 event.type = fcoe->event_type; 8494 event.index = UINT32_MAX; 8495 8496 switch (fcoe->event_type) { 8497 case SLI4_FCOE_FIP_FCF_DISCOVERED: 8498 ocs_log_debug(sli4->os, "FCF Discovered index=%d\n", fcoe->event_information); 8499 break; 8500 case SLI4_FCOE_FIP_FCF_TABLE_FULL: 8501 ocs_log_debug(sli4->os, "FCF Table Full\n"); 8502 mask = 0; 8503 break; 8504 case SLI4_FCOE_FIP_FCF_DEAD: 8505 ocs_log_debug(sli4->os, "FCF Dead/Gone index=%d\n", fcoe->event_information); 8506 break; 8507 case SLI4_FCOE_FIP_FCF_CLEAR_VLINK: 8508 mask = UINT16_MAX; 8509 ocs_log_debug(sli4->os, "Clear VLINK Received VPI=%#x\n", fcoe->event_information & mask); 8510 break; 8511 case SLI4_FCOE_FIP_FCF_MODIFIED: 8512 ocs_log_debug(sli4->os, "FCF Modified\n"); 8513 break; 8514 default: 8515 ocs_log_test(sli4->os, "bad FCoE type %#x", fcoe->event_type); 8516 mask = 0; 8517 } 8518 8519 if (mask != 0) { 8520 event.index = fcoe->event_information & mask; 8521 } 8522 8523 sli4->fip(sli4->fip_arg, &event); 8524 8525 return 0; 8526 } 8527 8528 /** 8529 * @ingroup sli_fc 8530 * @brief Allocate a receive queue. 8531 * 8532 * @par Description 8533 * Allocates DMA memory and configures the requested queue type. 8534 * 8535 * @param sli4 SLI context. 8536 * @param q Pointer to the queue object for the header. 8537 * @param n_entries Number of entries to allocate. 8538 * @param buffer_size buffer size for the queue. 8539 * @param cq Associated CQ. 8540 * @param ulp The ULP to bind 8541 * @param is_hdr Used to validate the rq_id and set the type of queue 8542 * 8543 * @return Returns 0 on success, or -1 on failure. 8544 */ 8545 int32_t 8546 sli_fc_rq_alloc(sli4_t *sli4, sli4_queue_t *q, 8547 uint32_t n_entries, uint32_t buffer_size, 8548 sli4_queue_t *cq, uint16_t ulp, uint8_t is_hdr) 8549 { 8550 int32_t (*rq_create)(sli4_t *, void *, size_t, ocs_dma_t *, uint16_t, uint16_t, uint16_t); 8551 8552 if ((sli4 == NULL) || (q == NULL)) { 8553 void *os = sli4 != NULL ? sli4->os : NULL; 8554 8555 ocs_log_err(os, "bad parameter sli4=%p q=%p\n", sli4, q); 8556 return -1; 8557 } 8558 8559 if (__sli_queue_init(sli4, q, SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE, 8560 n_entries, SLI_PAGE_SIZE)) { 8561 return -1; 8562 } 8563 8564 if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) { 8565 rq_create = sli_cmd_fcoe_rq_create; 8566 } else { 8567 rq_create = sli_cmd_fcoe_rq_create_v1; 8568 } 8569 8570 if (rq_create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma, 8571 cq->id, ulp, buffer_size)) { 8572 if (__sli_create_queue(sli4, q)) { 8573 ocs_dma_free(sli4->os, &q->dma); 8574 return -1; 8575 } 8576 if (is_hdr && q->id & 1) { 8577 ocs_log_test(sli4->os, "bad header RQ_ID %d\n", q->id); 8578 ocs_dma_free(sli4->os, &q->dma); 8579 return -1; 8580 } else if (!is_hdr && (q->id & 1) == 0) { 8581 ocs_log_test(sli4->os, "bad data RQ_ID %d\n", q->id); 8582 ocs_dma_free(sli4->os, &q->dma); 8583 return -1; 8584 } 8585 } else { 8586 return -1; 8587 } 8588 q->u.flag.is_hdr = is_hdr; 8589 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) { 8590 q->u.flag.rq_batch = TRUE; 8591 } 8592 return 0; 8593 } 8594 8595 /** 8596 * @ingroup sli_fc 8597 * @brief Allocate a receive queue set. 8598 * 8599 * @param sli4 SLI context. 8600 * @param num_rq_pairs to create 8601 * @param qs Pointers to the queue objects for both header and data. 8602 * Length of this arrays should be 2 * num_rq_pairs 8603 * @param base_cq_id. Assumes base_cq_id : (base_cq_id + num_rq_pairs) cqs as allotted. 8604 * @param n_entries number of entries in each RQ queue. 8605 * @param header_buffer_size 8606 * @param payload_buffer_size 8607 * @param ulp The ULP to bind 8608 * 8609 * @return Returns 0 on success, or -1 on failure. 8610 */ 8611 int32_t 8612 sli_fc_rq_set_alloc(sli4_t *sli4, uint32_t num_rq_pairs, 8613 sli4_queue_t *qs[], uint32_t base_cq_id, 8614 uint32_t n_entries, uint32_t header_buffer_size, 8615 uint32_t payload_buffer_size, uint16_t ulp) 8616 { 8617 uint32_t i, p, offset = 0; 8618 uint32_t payload_size, total_page_count = 0; 8619 uintptr_t addr; 8620 ocs_dma_t dma; 8621 sli4_res_common_create_queue_set_t *rsp = NULL; 8622 sli4_req_fcoe_rq_create_v2_t *req = NULL; 8623 8624 ocs_memset(&dma, 0, sizeof(dma)); 8625 8626 for (i = 0; i < (num_rq_pairs * 2); i++) { 8627 if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE, 8628 n_entries, SLI_PAGE_SIZE)) { 8629 goto error; 8630 } 8631 } 8632 8633 total_page_count = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE) * num_rq_pairs * 2; 8634 8635 /* Payload length must accommodate both request and response */ 8636 payload_size = max((sizeof(sli4_req_fcoe_rq_create_v1_t) + (8 * total_page_count)), 8637 sizeof(sli4_res_common_create_queue_set_t)); 8638 8639 if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) { 8640 ocs_log_err(sli4->os, "DMA allocation failed\n"); 8641 goto error; 8642 } 8643 ocs_memset(dma.virt, 0, payload_size); 8644 8645 if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 8646 payload_size, &dma) == -1) { 8647 goto error; 8648 } 8649 req = (sli4_req_fcoe_rq_create_v2_t *)((uint8_t *)dma.virt); 8650 8651 /* Fill Header fields */ 8652 req->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE; 8653 req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE; 8654 req->hdr.version = 2; 8655 req->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v2_t) - sizeof(sli4_req_hdr_t) 8656 + (8 * total_page_count); 8657 8658 /* Fill Payload fields */ 8659 req->dnb = TRUE; 8660 req->num_pages = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE); 8661 req->rqe_count = qs[0]->dma.size / SLI4_FCOE_RQE_SIZE; 8662 req->rqe_size = SLI4_FCOE_RQE_SIZE_8; 8663 req->page_size = SLI4_FCOE_RQ_PAGE_SIZE_4096; 8664 req->rq_count = num_rq_pairs * 2; 8665 req->base_cq_id = base_cq_id; 8666 req->hdr_buffer_size = header_buffer_size; 8667 req->payload_buffer_size = payload_buffer_size; 8668 8669 for (i = 0; i < (num_rq_pairs * 2); i++) { 8670 for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += SLI_PAGE_SIZE) { 8671 req->page_physical_address[offset].low = ocs_addr32_lo(addr); 8672 req->page_physical_address[offset].high = ocs_addr32_hi(addr); 8673 offset++; 8674 } 8675 } 8676 8677 if (sli_bmbx_command(sli4)){ 8678 ocs_log_crit(sli4->os, "bootstrap mailbox write failed RQSet\n"); 8679 goto error; 8680 } 8681 8682 rsp = (void *)((uint8_t *)dma.virt); 8683 if (rsp->hdr.status) { 8684 ocs_log_err(sli4->os, "bad create RQSet status=%#x addl=%#x\n", 8685 rsp->hdr.status, rsp->hdr.additional_status); 8686 goto error; 8687 } else { 8688 for (i = 0; i < (num_rq_pairs * 2); i++) { 8689 qs[i]->id = i + rsp->q_id; 8690 if ((qs[i]->id & 1) == 0) { 8691 qs[i]->u.flag.is_hdr = TRUE; 8692 } else { 8693 qs[i]->u.flag.is_hdr = FALSE; 8694 } 8695 qs[i]->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off; 8696 qs[i]->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset; 8697 } 8698 } 8699 8700 ocs_dma_free(sli4->os, &dma); 8701 8702 return 0; 8703 8704 error: 8705 for (i = 0; i < (num_rq_pairs * 2); i++) { 8706 if (qs[i]->dma.size) { 8707 ocs_dma_free(sli4->os, &qs[i]->dma); 8708 } 8709 } 8710 8711 if (dma.size) { 8712 ocs_dma_free(sli4->os, &dma); 8713 } 8714 8715 return -1; 8716 } 8717 8718 /** 8719 * @ingroup sli_fc 8720 * @brief Get the RPI resource requirements. 8721 * 8722 * @param sli4 SLI context. 8723 * @param n_rpi Number of RPIs desired. 8724 * 8725 * @return Returns the number of bytes needed. This value may be zero. 8726 */ 8727 uint32_t 8728 sli_fc_get_rpi_requirements(sli4_t *sli4, uint32_t n_rpi) 8729 { 8730 uint32_t bytes = 0; 8731 8732 /* Check if header templates needed */ 8733 if (sli4->config.hdr_template_req) { 8734 /* round up to a page */ 8735 bytes = SLI_ROUND_PAGE(n_rpi * SLI4_FCOE_HDR_TEMPLATE_SIZE); 8736 } 8737 8738 return bytes; 8739 } 8740 8741 /** 8742 * @ingroup sli_fc 8743 * @brief Return a text string corresponding to a CQE status value 8744 * 8745 * @param status Status value 8746 * 8747 * @return Returns corresponding string, otherwise "unknown" 8748 */ 8749 const char * 8750 sli_fc_get_status_string(uint32_t status) 8751 { 8752 static struct { 8753 uint32_t code; 8754 const char *label; 8755 } lookup[] = { 8756 {SLI4_FC_WCQE_STATUS_SUCCESS, "SUCCESS"}, 8757 {SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE, "FCP_RSP_FAILURE"}, 8758 {SLI4_FC_WCQE_STATUS_REMOTE_STOP, "REMOTE_STOP"}, 8759 {SLI4_FC_WCQE_STATUS_LOCAL_REJECT, "LOCAL_REJECT"}, 8760 {SLI4_FC_WCQE_STATUS_NPORT_RJT, "NPORT_RJT"}, 8761 {SLI4_FC_WCQE_STATUS_FABRIC_RJT, "FABRIC_RJT"}, 8762 {SLI4_FC_WCQE_STATUS_NPORT_BSY, "NPORT_BSY"}, 8763 {SLI4_FC_WCQE_STATUS_FABRIC_BSY, "FABRIC_BSY"}, 8764 {SLI4_FC_WCQE_STATUS_LS_RJT, "LS_RJT"}, 8765 {SLI4_FC_WCQE_STATUS_CMD_REJECT, "CMD_REJECT"}, 8766 {SLI4_FC_WCQE_STATUS_FCP_TGT_LENCHECK, "FCP_TGT_LENCHECK"}, 8767 {SLI4_FC_WCQE_STATUS_RQ_BUF_LEN_EXCEEDED, "BUF_LEN_EXCEEDED"}, 8768 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_BUF_NEEDED, "RQ_INSUFF_BUF_NEEDED"}, 8769 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_FRM_DISC, "RQ_INSUFF_FRM_DESC"}, 8770 {SLI4_FC_WCQE_STATUS_RQ_DMA_FAILURE, "RQ_DMA_FAILURE"}, 8771 {SLI4_FC_WCQE_STATUS_FCP_RSP_TRUNCATE, "FCP_RSP_TRUNCATE"}, 8772 {SLI4_FC_WCQE_STATUS_DI_ERROR, "DI_ERROR"}, 8773 {SLI4_FC_WCQE_STATUS_BA_RJT, "BA_RJT"}, 8774 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_NEEDED, "RQ_INSUFF_XRI_NEEDED"}, 8775 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_DISC, "INSUFF_XRI_DISC"}, 8776 {SLI4_FC_WCQE_STATUS_RX_ERROR_DETECT, "RX_ERROR_DETECT"}, 8777 {SLI4_FC_WCQE_STATUS_RX_ABORT_REQUEST, "RX_ABORT_REQUEST"}, 8778 }; 8779 uint32_t i; 8780 8781 for (i = 0; i < ARRAY_SIZE(lookup); i++) { 8782 if (status == lookup[i].code) { 8783 return lookup[i].label; 8784 } 8785 } 8786 return "unknown"; 8787 } 8788