1 /*- 2 * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 27 #include "smartpqi_includes.h" 28 29 /* 30 * Submit an admin IU to the adapter. 31 * TODO : Admin command implemented using polling, 32 * Add interrupt support, if required 33 */ 34 int 35 pqisrc_submit_admin_req(pqisrc_softstate_t *softs, 36 gen_adm_req_iu_t *req, gen_adm_resp_iu_t *resp) 37 { 38 int ret = PQI_STATUS_SUCCESS; 39 ob_queue_t *ob_q = &softs->admin_ob_queue; 40 ib_queue_t *ib_q = &softs->admin_ib_queue; 41 int tmo = PQISRC_ADMIN_CMD_RESP_TIMEOUT; 42 43 DBG_FUNC("IN\n"); 44 45 req->header.iu_type = 46 PQI_IU_TYPE_GENERAL_ADMIN_REQUEST; 47 req->header.comp_feature = 0x00; 48 req->header.iu_length = PQI_STANDARD_IU_LENGTH; 49 req->res1 = 0; 50 req->work = 0; 51 52 /* Get the tag */ 53 req->req_id = pqisrc_get_tag(&softs->taglist); 54 if (INVALID_ELEM == req->req_id) { 55 DBG_ERR("Tag not available0x%x\n",(uint16_t)req->req_id); 56 ret = PQI_STATUS_FAILURE; 57 goto err_out; 58 } 59 softs->rcb[req->req_id].tag = req->req_id; 60 61 /* Submit the command to the admin ib queue */ 62 ret = pqisrc_submit_cmnd(softs, ib_q, req); 63 if (ret != PQI_STATUS_SUCCESS) { 64 DBG_ERR("Unable to submit command\n"); 65 goto err_cmd; 66 } 67 68 /* Wait for completion */ 69 COND_WAIT((*(ob_q->pi_virt_addr) != ob_q->ci_local), tmo); 70 if (tmo <= 0) { 71 DBG_ERR("Admin cmd timeout\n"); 72 DBG_ERR("tmo : %d\n",tmo); \ 73 /* TODO : PQI device status and error register and report */ 74 ret = PQI_STATUS_TIMEOUT; 75 goto err_cmd; 76 } 77 78 /* Copy the response */ 79 memcpy(resp, ob_q->array_virt_addr + (ob_q->ci_local * ob_q->elem_size), 80 sizeof(gen_adm_resp_iu_t)); 81 82 /* Update CI */ 83 ob_q->ci_local = (ob_q->ci_local + 1 ) % ob_q->num_elem; 84 PCI_MEM_PUT32(softs, ob_q->ci_register_abs, 85 ob_q->ci_register_offset, LE_32(ob_q->ci_local)); 86 87 /* Validate the response data */ 88 ASSERT(req->fn_code == resp->fn_code); 89 ASSERT(resp->header.iu_type == PQI_IU_TYPE_GENERAL_ADMIN_RESPONSE); 90 ret = resp->status; 91 if (ret) 92 goto err_cmd; 93 94 os_reset_rcb(&softs->rcb[req->req_id]); 95 pqisrc_put_tag(&softs->taglist,req->req_id); 96 DBG_FUNC("OUT\n"); 97 return ret; 98 err_cmd: 99 os_reset_rcb(&softs->rcb[req->req_id]); 100 pqisrc_put_tag(&softs->taglist,req->req_id); 101 err_out: 102 DBG_FUNC("failed OUT : %d\n", ret); 103 return ret; 104 } 105 106 /* 107 * Get the administration queue config parameters. 108 */ 109 void 110 pqisrc_get_admin_queue_config(pqisrc_softstate_t *softs) 111 { 112 uint64_t val = 0; 113 114 115 val = LE_64(PCI_MEM_GET64(softs, &softs->pqi_reg->pqi_dev_adminq_cap, PQI_ADMINQ_CAP)); 116 117 /* pqi_cap = (struct pqi_dev_adminq_cap *)&val;*/ 118 softs->admin_ib_queue.num_elem = val & 0xFF; 119 softs->admin_ob_queue.num_elem = (val & 0xFF00) >> 8; 120 /* Note : size in unit of 16 byte s*/ 121 softs->admin_ib_queue.elem_size = ((val & 0xFF0000) >> 16) * 16; 122 softs->admin_ob_queue.elem_size = ((val & 0xFF000000) >> 24) * 16; 123 124 DBG_INIT(" admin ib: num_elem=%u elem_size=%u\n", 125 softs->admin_ib_queue.num_elem, softs->admin_ib_queue.elem_size); 126 DBG_INIT(" admin ob: num_elem=%u elem_size=%u\n", 127 softs->admin_ob_queue.num_elem, softs->admin_ob_queue.elem_size); 128 } 129 130 /* 131 * Decide the no of elements in admin ib and ob queues. 132 */ 133 void 134 pqisrc_decide_admin_queue_config(pqisrc_softstate_t *softs) 135 { 136 /* Determine num elements in Admin IBQ */ 137 softs->admin_ib_queue.num_elem = MIN(softs->admin_ib_queue.num_elem, 138 PQISRC_MAX_ADMIN_IB_QUEUE_ELEM_NUM); 139 140 /* Determine num elements in Admin OBQ */ 141 softs->admin_ob_queue.num_elem = MIN(softs->admin_ob_queue.num_elem, 142 PQISRC_MAX_ADMIN_OB_QUEUE_ELEM_NUM); 143 } 144 145 /* 146 * Allocate DMA memory for inbound queue and initialize. 147 */ 148 int 149 pqisrc_allocate_and_init_inbound_q(pqisrc_softstate_t *softs, ib_queue_t *ib_q, char *tag) 150 { 151 struct dma_mem *dma_mem = &ib_q->alloc_dma; 152 uint32_t ib_array_size = 0; 153 uint32_t alloc_size = 0; 154 char *virt_addr = NULL; 155 dma_addr_t dma_addr = 0; 156 int ret = PQI_STATUS_SUCCESS; 157 158 ib_array_size = ib_q->num_elem * ib_q->elem_size; 159 ASSERT(ib_array_size > 0); 160 161 alloc_size = ib_array_size + PQI_CI_PI_ALIGN + PQI_ADDR_ALIGN; /* for IB CI and OB PI */ 162 163 /* Allocate memory for the Q */ 164 memset(dma_mem, 0, sizeof(*dma_mem)); 165 os_strlcpy(dma_mem->tag, tag, sizeof(dma_mem->tag)); 166 dma_mem->size = alloc_size; 167 dma_mem->align = PQI_ADDR_ALIGN; 168 ret = os_dma_mem_alloc(softs, &ib_q->alloc_dma); 169 if (ret) { 170 DBG_ERR("Failed to Allocate Q tag=%s ret=%d\n", dma_mem->tag, ret); 171 goto err_out; 172 } 173 174 DBG_INIT("alloc tag=%s size=0x%x align=0x%x virt_addr=%p dma_addr=%p\n", 175 dma_mem->tag, dma_mem->size, dma_mem->align, dma_mem->virt_addr, (void*)dma_mem->dma_addr); 176 177 /* Setup the address */ 178 virt_addr = dma_mem->virt_addr; 179 dma_addr = dma_mem->dma_addr; 180 ASSERT(!((uint64_t)virt_addr & PQI_ADDR_ALIGN_MASK)); 181 ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK)); 182 183 /* IB */ 184 ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK)); 185 ib_q->array_virt_addr = virt_addr; 186 ib_q->array_dma_addr = dma_addr; 187 ib_q->pi_local = 0; 188 189 /* update addr for the next user */ 190 virt_addr += ib_array_size; 191 dma_addr += ib_array_size; 192 193 /* IB CI */ 194 ASSERT(!(dma_addr & PQI_CI_PI_ALIGN_MASK)); 195 ib_q->ci_virt_addr = (uint32_t*)virt_addr; 196 ib_q->ci_dma_addr = dma_addr; 197 198 /* update addr for the next user */ 199 virt_addr += PQI_CI_PI_ALIGN; 200 201 DBG_INIT("ib_q: virt_addr=%p, ci_dma_addr=%p elem=%u size=%u\n", 202 ib_q->array_virt_addr, (void*)ib_q->ci_dma_addr, ib_q->num_elem, ib_array_size); 203 204 /* Verify we aren't out of bounds from allocation */ 205 ASSERT(virt_addr <= ((char*)dma_mem->virt_addr + alloc_size)); 206 207 DBG_FUNC("OUT\n"); 208 return ret; 209 210 err_out: 211 DBG_FUNC("failed OUT\n"); 212 return PQI_STATUS_FAILURE; 213 } 214 215 216 /* 217 * Allocate DMA memory for outbound queue and initialize. 218 */ 219 int 220 pqisrc_allocate_and_init_outbound_q(pqisrc_softstate_t *softs, ob_queue_t *ob_q, 221 char *tag) 222 { 223 struct dma_mem *dma_mem = &ob_q->alloc_dma; 224 uint32_t ob_array_size = 0; 225 uint32_t alloc_size = 0; 226 char *virt_addr = NULL; 227 dma_addr_t dma_addr = 0; 228 int ret = PQI_STATUS_SUCCESS; 229 230 ob_array_size = ob_q->num_elem * ob_q->elem_size; 231 ASSERT(ob_array_size > 0); 232 233 alloc_size = ob_array_size + PQI_CI_PI_ALIGN + PQI_ADDR_ALIGN; /* for OB PI */ 234 235 /* Allocate memory for the Q */ 236 memset(dma_mem, 0, sizeof(*dma_mem)); 237 os_strlcpy(dma_mem->tag, tag, sizeof(dma_mem->tag)); 238 dma_mem->size = alloc_size; 239 dma_mem->align = PQI_ADDR_ALIGN; 240 ret = os_dma_mem_alloc(softs, &ob_q->alloc_dma); 241 if (ret) { 242 DBG_ERR("Failed to Allocate Q tag=%s ret=%d\n", dma_mem->tag, ret); 243 goto err_out; 244 } 245 246 DBG_INIT("alloc tag=%s size=0x%x align=0x%x virt_addr=%p dma_addr=%p\n", 247 dma_mem->tag, dma_mem->size, dma_mem->align, dma_mem->virt_addr, (void*)dma_mem->dma_addr); 248 249 /* Setup the address */ 250 virt_addr = dma_mem->virt_addr; 251 dma_addr = dma_mem->dma_addr; 252 ASSERT(!((uint64_t)virt_addr & PQI_ADDR_ALIGN_MASK)); 253 ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK)); 254 255 ob_q->array_virt_addr = virt_addr; 256 ob_q->array_dma_addr = dma_addr; 257 ob_q->ci_local = 0; 258 259 /* update addr for the next user */ 260 virt_addr += ob_array_size; 261 dma_addr += ob_array_size; 262 263 /* OB PI */ 264 ASSERT(!(dma_addr & PQI_CI_PI_ALIGN_MASK)); 265 ob_q->pi_virt_addr = (uint32_t*)virt_addr; 266 ob_q->pi_dma_addr = dma_addr; 267 268 /* update addr to show the end next user */ 269 virt_addr += PQI_CI_PI_ALIGN; 270 271 DBG_INIT("ob_q: virt_addr=%p, pi_dma_addr=%p elem=%u size=%u\n", 272 ob_q->array_virt_addr, (void*)ob_q->pi_dma_addr, ob_q->num_elem, ob_array_size); 273 274 /* Verify we aren't out of bounds from allocation */ 275 ASSERT(virt_addr <= ((char*)dma_mem->virt_addr + alloc_size)); 276 277 DBG_FUNC("OUT\n"); 278 return ret; 279 280 err_out: 281 DBG_FUNC("failed OUT\n"); 282 return PQI_STATUS_FAILURE; 283 } 284 285 /* 286 * Allocate DMA memory for admin queue and initialize. 287 */ 288 int pqisrc_allocate_and_init_adminq(pqisrc_softstate_t *softs) 289 { 290 int ret; 291 ib_queue_t *admin_ib_q = &softs->admin_ib_queue; 292 ob_queue_t *admin_ob_q = &softs->admin_ob_queue; 293 294 ret = pqisrc_allocate_and_init_inbound_q(softs, admin_ib_q, "admin_queue"); 295 if (!ret) { 296 admin_ib_q->q_id = PQI_ADMIN_IB_QUEUE_ID; 297 ret = pqisrc_allocate_and_init_outbound_q(softs, admin_ob_q, "admin_queue"); 298 if(!ret) 299 admin_ob_q->q_id = PQI_ADMIN_OB_QUEUE_ID; 300 else { 301 if(softs->admin_ib_queue.lockcreated==true) { 302 OS_UNINIT_PQILOCK(&softs->admin_ib_queue.lock); 303 softs->admin_ib_queue.lockcreated = false; 304 } 305 if (softs->admin_ib_queue.alloc_dma.virt_addr) 306 os_dma_mem_free(softs, &softs->admin_ib_queue.alloc_dma); 307 } 308 } 309 else 310 DBG_ERR("Failed to create Admin Queue pair\n"); 311 312 return ret; 313 } 314 315 /* 316 * Subroutine used to create (or) delete the admin queue requested. 317 */ 318 int 319 pqisrc_create_delete_adminq(pqisrc_softstate_t *softs, uint32_t cmd) 320 { 321 int tmo = 0; 322 int ret = PQI_STATUS_SUCCESS; 323 324 /* Create Admin Q pair writing to Admin Q config function reg */ 325 326 PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG, LE_64(cmd)); 327 328 if (cmd == PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR) 329 tmo = PQISRC_ADMIN_QUEUE_CREATE_TIMEOUT; 330 else 331 tmo = PQISRC_ADMIN_QUEUE_DELETE_TIMEOUT; 332 333 /* Wait for completion */ 334 COND_WAIT((PCI_MEM_GET64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG) == 335 PQI_ADMIN_QUEUE_CONF_FUNC_STATUS_IDLE), tmo); 336 if (tmo <= 0) { 337 DBG_ERR("Unable to create/delete admin queue pair\n"); 338 /* TODO : PQI device status and error register and report */ 339 ret = PQI_STATUS_TIMEOUT; 340 } 341 342 return ret; 343 } 344 345 /* 346 * Debug admin queue configuration params. 347 */ 348 void 349 pqisrc_print_adminq_config(pqisrc_softstate_t *softs) 350 { 351 DBG_INFO(" softs->admin_ib_queue.array_dma_addr : %p\n", 352 (void*)softs->admin_ib_queue.array_dma_addr); 353 DBG_INFO(" softs->admin_ib_queue.array_virt_addr : %p\n", 354 (void*)softs->admin_ib_queue.array_virt_addr); 355 DBG_INFO(" softs->admin_ib_queue.num_elem : %u\n", 356 softs->admin_ib_queue.num_elem); 357 DBG_INFO(" softs->admin_ib_queue.elem_size : %u\n", 358 softs->admin_ib_queue.elem_size); 359 DBG_INFO(" softs->admin_ob_queue.array_dma_addr : %p\n", 360 (void*)softs->admin_ob_queue.array_dma_addr); 361 DBG_INFO(" softs->admin_ob_queue.array_virt_addr : %p\n", 362 (void*)softs->admin_ob_queue.array_virt_addr); 363 DBG_INFO(" softs->admin_ob_queue.num_elem : %u\n", 364 softs->admin_ob_queue.num_elem); 365 DBG_INFO(" softs->admin_ob_queue.elem_size : %u\n", 366 softs->admin_ob_queue.elem_size); 367 DBG_INFO(" softs->admin_ib_queue.pi_register_abs : %p\n", 368 (void*)softs->admin_ib_queue.pi_register_abs); 369 DBG_INFO(" softs->admin_ob_queue.ci_register_abs : %p\n", 370 (void*)softs->admin_ob_queue.ci_register_abs); 371 } 372 373 /* 374 * Function used to create an admin queue. 375 */ 376 int 377 pqisrc_create_admin_queue(pqisrc_softstate_t *softs) 378 { 379 int ret = PQI_STATUS_SUCCESS; 380 /* struct pqi_dev_adminq_cap *pqi_cap; */ 381 uint32_t admin_q_param = 0; 382 383 DBG_FUNC("IN\n"); 384 385 /* Get admin queue details - pqi2-r00a - table 24 */ 386 pqisrc_get_admin_queue_config(softs); 387 388 /* Decide admin Q config */ 389 pqisrc_decide_admin_queue_config(softs); 390 391 /* Allocate and init Admin Q pair */ 392 ret = pqisrc_allocate_and_init_adminq(softs); 393 if (ret) { 394 DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret); 395 goto err_out; 396 } 397 398 /* Write IB Q element array address */ 399 PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_elem_array_addr, 400 PQI_ADMIN_IBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ib_queue.array_dma_addr)); 401 402 /* Write OB Q element array address */ 403 PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_elem_array_addr, 404 PQI_ADMIN_OBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ob_queue.array_dma_addr)); 405 406 /* Write IB Q CI address */ 407 PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_ci_addr, 408 PQI_ADMIN_IBQ_CI_ADDR, LE_64(softs->admin_ib_queue.ci_dma_addr)); 409 410 /* Write OB Q PI address */ 411 PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_pi_addr, 412 PQI_ADMIN_OBQ_PI_ADDR, LE_64(softs->admin_ob_queue.pi_dma_addr)); 413 414 415 /* Write Admin Q params pqi-r200a table 36 */ 416 417 admin_q_param = softs->admin_ib_queue.num_elem | 418 (softs->admin_ob_queue.num_elem << 8)| 419 PQI_ADMIN_QUEUE_MSIX_DISABLE; 420 421 PCI_MEM_PUT32(softs, &softs->pqi_reg->admin_q_param, 422 PQI_ADMINQ_PARAM, LE_32(admin_q_param)); 423 424 /* Submit cmd to create Admin Q pair */ 425 ret = pqisrc_create_delete_adminq(softs, 426 PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR); 427 if (ret) { 428 DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret); 429 goto err_q_create; 430 } 431 432 /* Admin queue created, get ci,pi offset */ 433 softs->admin_ib_queue.pi_register_offset =(PQISRC_PQI_REG_OFFSET + 434 PCI_MEM_GET64(softs, &softs->pqi_reg->admin_ibq_pi_offset, PQI_ADMIN_IBQ_PI_OFFSET)); 435 436 softs->admin_ib_queue.pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + 437 softs->admin_ib_queue.pi_register_offset); 438 439 softs->admin_ob_queue.ci_register_offset = (PQISRC_PQI_REG_OFFSET + 440 PCI_MEM_GET64(softs, &softs->pqi_reg->admin_obq_ci_offset, PQI_ADMIN_OBQ_CI_OFFSET)); 441 442 softs->admin_ob_queue.ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + 443 softs->admin_ob_queue.ci_register_offset); 444 445 os_strlcpy(softs->admin_ib_queue.lockname, "admin_ibqlock", LOCKNAME_SIZE); 446 447 ret =OS_INIT_PQILOCK(softs, &softs->admin_ib_queue.lock, 448 softs->admin_ib_queue.lockname); 449 if(ret){ 450 DBG_ERR("Admin spinlock initialization failed\n"); 451 softs->admin_ib_queue.lockcreated = false; 452 goto err_lock; 453 } 454 softs->admin_ib_queue.lockcreated = true; 455 456 /* Print admin q config details */ 457 pqisrc_print_adminq_config(softs); 458 459 DBG_FUNC("OUT\n"); 460 return ret; 461 462 err_lock: 463 #if 0 464 pqisrc_create_delete_adminq(softs, PQI_ADMIN_QUEUE_CONF_FUNC_DEL_Q_PAIR); 465 #endif 466 err_q_create: 467 pqisrc_destroy_admin_queue(softs); 468 err_out: 469 DBG_FUNC("failed OUT\n"); 470 return ret; 471 } 472 473 /* 474 * Subroutine used to delete an operational queue. 475 */ 476 int 477 pqisrc_delete_op_queue(pqisrc_softstate_t *softs, 478 uint32_t q_id, boolean_t ibq) 479 { 480 int ret = PQI_STATUS_SUCCESS; 481 /* Firmware doesn't support this now */ 482 483 #if 0 484 gen_adm_req_iu_t admin_req; 485 gen_adm_resp_iu_t admin_resp; 486 487 488 memset(&admin_req, 0, sizeof(admin_req)); 489 memset(&admin_resp, 0, sizeof(admin_resp)); 490 491 DBG_FUNC("IN\n"); 492 493 admin_req.req_type.create_op_iq.qid = q_id; 494 495 if (ibq) 496 admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_IQ; 497 else 498 admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_OQ; 499 500 501 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 502 503 DBG_FUNC("OUT\n"); 504 #endif 505 return ret; 506 } 507 508 /* 509 * Function used to destroy the event queue. 510 */ 511 void 512 pqisrc_destroy_event_queue(pqisrc_softstate_t *softs) 513 { 514 DBG_FUNC("IN\n"); 515 516 if (softs->event_q.created == true) { 517 int ret = PQI_STATUS_SUCCESS; 518 ret = pqisrc_delete_op_queue(softs, softs->event_q.q_id, false); 519 if (ret) { 520 DBG_ERR("Failed to Delete Event Q %u\n", softs->event_q.q_id); 521 } 522 softs->event_q.created = false; 523 } 524 525 /* Free the memory */ 526 if (softs->event_q.alloc_dma.virt_addr) 527 os_dma_mem_free(softs, &softs->event_q.alloc_dma); 528 529 DBG_FUNC("OUT\n"); 530 } 531 532 /* 533 * Function used to destroy operational ib queues. 534 */ 535 void 536 pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs) 537 { 538 int ret = PQI_STATUS_SUCCESS; 539 ib_queue_t *op_ib_q = NULL; 540 uint32_t total_op_ibq = softs->num_op_raid_ibq; 541 int i; 542 543 DBG_FUNC("IN\n"); 544 545 for (i = 0; i < total_op_ibq; i++) { 546 int repeat = 0; 547 /* RAID first */ 548 op_ib_q = &softs->op_raid_ib_q[i]; 549 release_queue: 550 if (op_ib_q->created == true) { 551 ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, 552 true); 553 if (ret) { 554 DBG_ERR("Failed to Delete IB Q %u\n", 555 op_ib_q->q_id); 556 } 557 op_ib_q->created = false; 558 } 559 560 if (op_ib_q->lockcreated == true) { 561 OS_UNINIT_PQILOCK(&op_ib_q->lock); 562 op_ib_q->lockcreated = false; 563 } 564 565 /* Free the memory */ 566 if (op_ib_q->alloc_dma.virt_addr) 567 os_dma_mem_free(softs, &op_ib_q->alloc_dma); 568 569 if (repeat < 1) { 570 repeat++; 571 op_ib_q = &softs->op_aio_ib_q[i]; 572 goto release_queue; 573 } 574 } 575 576 DBG_FUNC("OUT\n"); 577 } 578 579 /* 580 * Function used to destroy operational ob queues. 581 */ 582 void 583 pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) 584 { 585 int ret = PQI_STATUS_SUCCESS; 586 int i; 587 ob_queue_t *op_ob_q = NULL; 588 589 DBG_FUNC("IN\n"); 590 591 for (i = 0; i < softs->num_op_obq; i++) { 592 op_ob_q = &softs->op_ob_q[i]; 593 594 if (op_ob_q->created == true) { 595 ret = pqisrc_delete_op_queue(softs, op_ob_q->q_id, false); 596 if (ret) { 597 DBG_ERR("Failed to Delete OB Q %u\n",op_ob_q->q_id); 598 } 599 op_ob_q->created = false; 600 } 601 602 /* Free the memory */ 603 if (op_ob_q->alloc_dma.virt_addr) 604 os_dma_mem_free(softs, &op_ob_q->alloc_dma); 605 } 606 607 /* Free the memory */ 608 DBG_FUNC("OUT\n"); 609 } 610 611 /* 612 * Function used to destroy an admin queue. 613 */ 614 int 615 pqisrc_destroy_admin_queue(pqisrc_softstate_t *softs) 616 { 617 int ret = PQI_STATUS_SUCCESS; 618 619 DBG_FUNC("IN\n"); 620 621 if(softs->admin_ib_queue.lockcreated==true) { 622 OS_UNINIT_PQILOCK(&softs->admin_ib_queue.lock); 623 softs->admin_ib_queue.lockcreated = false; 624 } 625 626 #if 0 627 ret = pqisrc_create_delete_adminq(softs, 628 PQI_ADMIN_QUEUE_CONF_FUNC_DEL_Q_PAIR); 629 #endif 630 631 if (softs->admin_ib_queue.alloc_dma.virt_addr) 632 os_dma_mem_free(softs, &softs->admin_ib_queue.alloc_dma); 633 634 if (softs->admin_ob_queue.alloc_dma.virt_addr) 635 os_dma_mem_free(softs, &softs->admin_ob_queue.alloc_dma); 636 637 DBG_FUNC("OUT\n"); 638 return ret; 639 } 640 641 /* 642 * Function used to change operational ib queue properties. 643 */ 644 int 645 pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *softs, 646 ib_queue_t *op_ib_q, uint32_t prop) 647 { 648 int ret = PQI_STATUS_SUCCESS; 649 gen_adm_req_iu_t admin_req; 650 gen_adm_resp_iu_t admin_resp; 651 652 memset(&admin_req, 0, sizeof(admin_req)); 653 memset(&admin_resp, 0, sizeof(admin_resp)); 654 655 DBG_FUNC("IN\n"); 656 657 admin_req.fn_code = PQI_FUNCTION_CHANGE_OPERATIONAL_IQ_PROP; 658 admin_req.req_type.change_op_iq_prop.qid = op_ib_q->q_id; 659 admin_req.req_type.change_op_iq_prop.vend_specific = prop; 660 661 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 662 663 DBG_FUNC("OUT\n"); 664 return ret; 665 } 666 667 /* 668 * Function used to create an operational ob queue. 669 */ 670 int 671 pqisrc_create_op_obq(pqisrc_softstate_t *softs, 672 ob_queue_t *op_ob_q) 673 { 674 int ret = PQI_STATUS_SUCCESS; 675 gen_adm_req_iu_t admin_req; 676 gen_adm_resp_iu_t admin_resp; 677 678 DBG_FUNC("IN\n"); 679 680 memset(&admin_req, 0, sizeof(admin_req)); 681 memset(&admin_resp, 0, sizeof(admin_resp)); 682 683 admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_OQ; 684 admin_req.req_type.create_op_oq.qid = op_ob_q->q_id; 685 admin_req.req_type.create_op_oq.intr_msg_num = op_ob_q->intr_msg_num; 686 admin_req.req_type.create_op_oq.elem_arr_addr = op_ob_q->array_dma_addr; 687 admin_req.req_type.create_op_oq.ob_pi_addr = op_ob_q->pi_dma_addr; 688 admin_req.req_type.create_op_oq.num_elem = op_ob_q->num_elem; 689 admin_req.req_type.create_op_oq.elem_len = op_ob_q->elem_size / 16; 690 691 DBG_INFO("admin_req.req_type.create_op_oq.qid : %x\n",admin_req.req_type.create_op_oq.qid); 692 DBG_INFO("admin_req.req_type.create_op_oq.intr_msg_num : %x\n", admin_req.req_type.create_op_oq.intr_msg_num ); 693 694 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 695 if( PQI_STATUS_SUCCESS == ret) { 696 op_ob_q->ci_register_offset = (PQISRC_PQI_REG_OFFSET + 697 admin_resp.resp_type.create_op_oq.ci_offset); 698 op_ob_q->ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + 699 op_ob_q->ci_register_offset); 700 } else { 701 int i = 0; 702 DBG_WARN("Error Status Descriptors\n"); 703 for(i = 0; i < 4;i++) 704 DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]); 705 } 706 707 DBG_FUNC("OUT ret : %d\n", ret); 708 709 return ret; 710 } 711 712 /* 713 * Function used to create an operational ib queue. 714 */ 715 int 716 pqisrc_create_op_ibq(pqisrc_softstate_t *softs, 717 ib_queue_t *op_ib_q) 718 { 719 int ret = PQI_STATUS_SUCCESS; 720 gen_adm_req_iu_t admin_req; 721 gen_adm_resp_iu_t admin_resp; 722 723 DBG_FUNC("IN\n"); 724 725 memset(&admin_req, 0, sizeof(admin_req)); 726 memset(&admin_resp, 0, sizeof(admin_resp)); 727 728 admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_IQ; 729 admin_req.req_type.create_op_iq.qid = op_ib_q->q_id; 730 admin_req.req_type.create_op_iq.elem_arr_addr = op_ib_q->array_dma_addr; 731 admin_req.req_type.create_op_iq.iq_ci_addr = op_ib_q->ci_dma_addr; 732 admin_req.req_type.create_op_iq.num_elem = op_ib_q->num_elem; 733 admin_req.req_type.create_op_iq.elem_len = op_ib_q->elem_size / 16; 734 735 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 736 737 if( PQI_STATUS_SUCCESS == ret) { 738 op_ib_q->pi_register_offset =(PQISRC_PQI_REG_OFFSET + 739 admin_resp.resp_type.create_op_iq.pi_offset); 740 741 op_ib_q->pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + 742 op_ib_q->pi_register_offset); 743 } else { 744 int i = 0; 745 DBG_WARN("Error Status Decsriptors\n"); 746 for(i = 0; i < 4;i++) 747 DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]); 748 } 749 750 DBG_FUNC("OUT ret : %d\n", ret); 751 return ret; 752 } 753 754 /* 755 * subroutine used to create an operational ib queue for AIO. 756 */ 757 int 758 pqisrc_create_op_aio_ibq(pqisrc_softstate_t *softs, 759 ib_queue_t *op_aio_ib_q) 760 { 761 int ret = PQI_STATUS_SUCCESS; 762 763 DBG_FUNC("IN\n"); 764 765 ret = pqisrc_create_op_ibq(softs,op_aio_ib_q); 766 if ( PQI_STATUS_SUCCESS == ret) 767 ret = pqisrc_change_op_ibq_queue_prop(softs, 768 op_aio_ib_q, PQI_CHANGE_OP_IQ_PROP_ASSIGN_AIO); 769 770 DBG_FUNC("OUT ret : %d\n", ret); 771 return ret; 772 } 773 774 /* 775 * subroutine used to create an operational ib queue for RAID. 776 */ 777 int 778 pqisrc_create_op_raid_ibq(pqisrc_softstate_t *softs, 779 ib_queue_t *op_raid_ib_q) 780 { 781 int ret = PQI_STATUS_SUCCESS; 782 783 DBG_FUNC("IN\n"); 784 785 ret = pqisrc_create_op_ibq(softs,op_raid_ib_q); 786 787 DBG_FUNC("OUT\n"); 788 return ret; 789 } 790 791 /* 792 * Allocate and create an event queue to process supported events. 793 */ 794 int 795 pqisrc_alloc_and_create_event_queue(pqisrc_softstate_t *softs) 796 { 797 int ret = PQI_STATUS_SUCCESS; 798 uint32_t num_elem; 799 ob_queue_t *event_q = &softs->event_q; 800 801 DBG_FUNC("IN\n"); 802 803 /* 804 * Calculate memory requirements. 805 * If event queue is shared for IO response, number of 806 * elements in event queue depends on num elements in OP OB Q 807 * also. Since event queue element size (32) is more than IO 808 * response size , event queue element size need not be checked 809 * for queue size calculation. 810 */ 811 #ifdef SHARE_EVENT_QUEUE_FOR_IO 812 num_elem = MIN(softs->num_elem_per_op_obq, PQISRC_MAX_EVENT_QUEUE_ELEM_NUM); 813 #else 814 num_elem = PQISRC_MAX_EVENT_QUEUE_ELEM_NUM; 815 #endif 816 817 event_q->num_elem = num_elem; 818 event_q->elem_size = PQISRC_EVENT_Q_ELEM_SIZE_BYTES; 819 820 ret = pqisrc_allocate_and_init_outbound_q(softs, event_q, "event_queue"); 821 822 if (ret) { 823 DBG_ERR("Failed to Allocate EventQ\n"); 824 goto err_out; 825 } 826 event_q->q_id = PQI_OP_EVENT_QUEUE_ID; 827 event_q->intr_msg_num = 0; /* vector zero for event */ 828 829 ret = pqisrc_create_op_obq(softs,event_q); 830 if (ret) { 831 DBG_ERR("Failed to Create EventQ %u\n",event_q->q_id); 832 goto err_out_create; 833 } 834 event_q->created = true; 835 836 DBG_FUNC("OUT\n"); 837 return ret; 838 839 err_out_create: 840 pqisrc_destroy_event_queue(softs); 841 err_out: 842 DBG_FUNC("OUT failed %d\n", ret); 843 return PQI_STATUS_FAILURE; 844 } 845 846 /* 847 * Allocate DMA memory and create operational ib queues. 848 */ 849 int 850 pqisrc_alloc_and_create_ib_queues(pqisrc_softstate_t *softs) 851 { 852 int ret = PQI_STATUS_SUCCESS; 853 ib_queue_t *op_ib_q = NULL; 854 uint32_t ibq_id = PQI_MIN_OP_IB_QUEUE_ID; 855 uint32_t total_op_ibq = softs->num_op_raid_ibq + softs->num_op_aio_ibq; 856 int i = 0; 857 char *string = NULL; 858 859 DBG_FUNC("IN\n"); 860 861 ASSERT(softs->num_op_raid_ibq == softs->num_op_aio_ibq); 862 863 for (i = 0; i < total_op_ibq; i++) { 864 865 /* OP RAID IB Q */ 866 if (i % 2 == 0) 867 { 868 op_ib_q = &softs->op_raid_ib_q[i/2]; 869 string = "raid"; 870 } 871 else 872 { 873 op_ib_q = &softs->op_aio_ib_q[i/2]; 874 string = "aio"; 875 } 876 877 /* Allocate memory for IB queues */ 878 op_ib_q->num_elem = softs->num_elem_per_op_ibq; 879 op_ib_q->elem_size = softs->max_ibq_elem_size; 880 881 ret = pqisrc_allocate_and_init_inbound_q(softs, op_ib_q, "op_ib_queue"); 882 if (ret) { 883 DBG_ERR("Failed to Allocate Operational IBQ memory ret : %d\n", 884 ret); 885 goto err_out; 886 } 887 op_ib_q->q_id = ibq_id++; 888 889 snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "%s_ibqlock_%d", string, i); 890 ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); 891 if(ret){ 892 /* TODO: error handling */ 893 DBG_ERR("%s %d init failed\n", string, i); 894 op_ib_q->lockcreated = false; 895 goto err_lock; 896 } 897 op_ib_q->lockcreated = true; 898 899 if (i % 2 == 0) 900 ret = pqisrc_create_op_raid_ibq(softs, op_ib_q); 901 else 902 ret = pqisrc_create_op_aio_ibq(softs, op_ib_q); 903 if (ret) { 904 DBG_ERR("Failed to Create OP IBQ type=%s id=%u\n", 905 string, op_ib_q->q_id); 906 goto err_out_create; 907 } 908 op_ib_q->created = true; 909 } 910 911 DBG_FUNC("OUT\n"); 912 return ret; 913 914 err_lock: 915 err_out_create: 916 err_out: 917 pqisrc_destroy_op_ib_queues(softs); 918 DBG_FUNC("OUT failed %d\n", ret); 919 return PQI_STATUS_FAILURE; 920 } 921 922 /* 923 * Allocate DMA memory and create operational ob queues. 924 */ 925 int 926 pqisrc_alloc_and_create_ob_queues(pqisrc_softstate_t *softs) 927 { 928 int ret = PQI_STATUS_SUCCESS; 929 uint32_t obq_id = PQI_MIN_OP_OB_QUEUE_ID; 930 ob_queue_t *op_ob_q = NULL; 931 int i = 0; 932 933 DBG_FUNC("IN\n"); 934 935 /* 936 * OB Q element array should be 64 byte aligned. 937 * So the number of elements in OB Q should be multiple 938 * of 4, so that OB Queue element size (16) * num elements 939 * will be multiple of 64. 940 */ 941 942 ALIGN_BOUNDARY(softs->num_elem_per_op_obq, 4); 943 944 DBG_INIT("softs->num_op_obq %u max_obq_elem_size=%u\n",softs->num_op_obq, softs->max_obq_elem_size); 945 946 for (i = 0; i < softs->num_op_obq; i++) { 947 op_ob_q = &softs->op_ob_q[i]; 948 949 /* Allocate memory for OB queues */ 950 op_ob_q->num_elem = softs->num_elem_per_op_obq; 951 op_ob_q->elem_size = PQISRC_OP_OBQ_ELEM_SIZE_BYTES; 952 ret = pqisrc_allocate_and_init_outbound_q(softs, op_ob_q, "op_ob_queue"); 953 if (ret) { 954 DBG_ERR("Failed to Allocate Operational OBQ memory ret : %d\n", 955 ret); 956 goto err_out; 957 } 958 op_ob_q->q_id = obq_id++; 959 if(softs->share_opq_and_eventq == true) 960 op_ob_q->intr_msg_num = i; 961 else 962 op_ob_q->intr_msg_num = i + 1; /* msg num zero for event */ 963 964 ret = pqisrc_create_op_obq(softs, op_ob_q); 965 if (ret) { 966 DBG_ERR("Failed to Create OP OBQ %u\n",op_ob_q->q_id); 967 goto err_out_create; 968 } 969 op_ob_q->created = true; 970 } 971 972 DBG_FUNC("OUT\n"); 973 return ret; 974 975 err_out_create: 976 err_out: 977 pqisrc_destroy_op_ob_queues(softs); 978 DBG_FUNC("OUT failed %d\n", ret); 979 return PQI_STATUS_FAILURE; 980 } 981 982 /* 983 * Function used to create operational queues for the adapter. 984 */ 985 int 986 pqisrc_create_op_queues(pqisrc_softstate_t *softs) 987 { 988 int ret = PQI_STATUS_SUCCESS; 989 990 DBG_FUNC("IN\n"); 991 992 /* Create Operational IB queues */ 993 ret = pqisrc_alloc_and_create_ib_queues(softs); 994 if (ret) 995 goto err_out; 996 /* Create Operational OB queues */ 997 ret = pqisrc_alloc_and_create_ob_queues(softs); 998 if (ret) 999 goto err_out_obq; 1000 1001 /* Create Event queue */ 1002 ret = pqisrc_alloc_and_create_event_queue(softs); 1003 if (ret) 1004 goto err_out_eventq; 1005 1006 DBG_FUNC("OUT\n"); 1007 return ret; 1008 err_out_eventq: 1009 pqisrc_destroy_op_ob_queues(softs); 1010 err_out_obq: 1011 pqisrc_destroy_op_ib_queues(softs); 1012 err_out: 1013 DBG_FUNC("OUT failed %d\n", ret); 1014 return PQI_STATUS_FAILURE; 1015 } 1016