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