1 /*- 2 * Copyright 2016-2025 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 pqisrc_delete_op_queue(softs, softs->event_q.q_id, false); 518 softs->event_q.created = false; 519 } 520 521 /* Free the memory */ 522 if (softs->event_q.alloc_dma.virt_addr) 523 os_dma_mem_free(softs, &softs->event_q.alloc_dma); 524 525 DBG_FUNC("OUT\n"); 526 } 527 528 /* 529 * Function used to destroy operational ib queues. 530 */ 531 void 532 pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs) 533 { 534 535 ib_queue_t *op_ib_q = NULL; 536 uint32_t total_op_ibq = softs->num_op_raid_ibq; 537 int i; 538 539 DBG_FUNC("IN\n"); 540 541 for (i = 0; i < total_op_ibq; i++) { 542 int repeat = 0; 543 /* RAID first */ 544 op_ib_q = &softs->op_raid_ib_q[i]; 545 release_queue: 546 if (op_ib_q->created == true) { 547 pqisrc_delete_op_queue(softs, op_ib_q->q_id, true); 548 op_ib_q->created = false; 549 } 550 551 if (op_ib_q->lockcreated == true) { 552 OS_UNINIT_PQILOCK(&op_ib_q->lock); 553 op_ib_q->lockcreated = false; 554 } 555 556 /* Free the memory */ 557 if (op_ib_q->alloc_dma.virt_addr) 558 os_dma_mem_free(softs, &op_ib_q->alloc_dma); 559 560 if (repeat < 1) { 561 repeat++; 562 op_ib_q = &softs->op_aio_ib_q[i]; 563 goto release_queue; 564 } 565 } 566 567 DBG_FUNC("OUT\n"); 568 } 569 570 /* 571 * Function used to destroy operational ob queues. 572 */ 573 void 574 pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) 575 { 576 int i; 577 ob_queue_t *op_ob_q = NULL; 578 579 DBG_FUNC("IN\n"); 580 581 for (i = 0; i < softs->num_op_obq; i++) { 582 op_ob_q = &softs->op_ob_q[i]; 583 584 if (op_ob_q->created == true) { 585 pqisrc_delete_op_queue(softs, op_ob_q->q_id, false); 586 op_ob_q->created = false; 587 } 588 589 /* Free the memory */ 590 if (op_ob_q->alloc_dma.virt_addr) 591 os_dma_mem_free(softs, &op_ob_q->alloc_dma); 592 } 593 594 /* Free the memory */ 595 DBG_FUNC("OUT\n"); 596 } 597 598 /* 599 * Function used to destroy an admin queue. 600 */ 601 int 602 pqisrc_destroy_admin_queue(pqisrc_softstate_t *softs) 603 { 604 int ret = PQI_STATUS_SUCCESS; 605 606 DBG_FUNC("IN\n"); 607 608 if(softs->admin_ib_queue.lockcreated==true) { 609 OS_UNINIT_PQILOCK(&softs->admin_ib_queue.lock); 610 softs->admin_ib_queue.lockcreated = false; 611 } 612 613 #if 0 614 ret = pqisrc_create_delete_adminq(softs, 615 PQI_ADMIN_QUEUE_CONF_FUNC_DEL_Q_PAIR); 616 #endif 617 618 if (softs->admin_ib_queue.alloc_dma.virt_addr) 619 os_dma_mem_free(softs, &softs->admin_ib_queue.alloc_dma); 620 621 if (softs->admin_ob_queue.alloc_dma.virt_addr) 622 os_dma_mem_free(softs, &softs->admin_ob_queue.alloc_dma); 623 624 DBG_FUNC("OUT\n"); 625 return ret; 626 } 627 628 /* 629 * Function used to change operational ib queue properties. 630 */ 631 int 632 pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *softs, 633 ib_queue_t const *op_ib_q, uint32_t prop) 634 { 635 int ret = PQI_STATUS_SUCCESS; 636 gen_adm_req_iu_t admin_req; 637 gen_adm_resp_iu_t admin_resp; 638 639 memset(&admin_req, 0, sizeof(admin_req)); 640 memset(&admin_resp, 0, sizeof(admin_resp)); 641 642 DBG_FUNC("IN\n"); 643 644 admin_req.fn_code = PQI_FUNCTION_CHANGE_OPERATIONAL_IQ_PROP; 645 admin_req.req_type.change_op_iq_prop.qid = op_ib_q->q_id; 646 admin_req.req_type.change_op_iq_prop.vend_specific = prop; 647 648 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 649 650 DBG_FUNC("OUT\n"); 651 return ret; 652 } 653 654 /* 655 * Function used to create an operational ob queue. 656 */ 657 int 658 pqisrc_create_op_obq(pqisrc_softstate_t *softs, 659 ob_queue_t *op_ob_q) 660 { 661 int ret = PQI_STATUS_SUCCESS; 662 gen_adm_req_iu_t admin_req; 663 gen_adm_resp_iu_t admin_resp; 664 665 DBG_FUNC("IN\n"); 666 667 memset(&admin_req, 0, sizeof(admin_req)); 668 memset(&admin_resp, 0, sizeof(admin_resp)); 669 670 admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_OQ; 671 admin_req.req_type.create_op_oq.qid = op_ob_q->q_id; 672 admin_req.req_type.create_op_oq.intr_msg_num = op_ob_q->intr_msg_num; 673 admin_req.req_type.create_op_oq.elem_arr_addr = op_ob_q->array_dma_addr; 674 admin_req.req_type.create_op_oq.ob_pi_addr = op_ob_q->pi_dma_addr; 675 admin_req.req_type.create_op_oq.num_elem = op_ob_q->num_elem; 676 admin_req.req_type.create_op_oq.elem_len = op_ob_q->elem_size / 16; 677 678 DBG_INFO("admin_req.req_type.create_op_oq.qid : %x\n",admin_req.req_type.create_op_oq.qid); 679 DBG_INFO("admin_req.req_type.create_op_oq.intr_msg_num : %x\n", admin_req.req_type.create_op_oq.intr_msg_num ); 680 681 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 682 if( PQI_STATUS_SUCCESS == ret) { 683 op_ob_q->ci_register_offset = (PQISRC_PQI_REG_OFFSET + 684 admin_resp.resp_type.create_op_oq.ci_offset); 685 op_ob_q->ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + 686 op_ob_q->ci_register_offset); 687 } else { 688 int i = 0; 689 DBG_WARN("Error Status Descriptors\n"); 690 for (i = 0; i < 4; i++) 691 DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]); 692 } 693 694 DBG_FUNC("OUT ret : %d\n", ret); 695 696 return ret; 697 } 698 699 /* 700 * Function used to create an operational ib queue. 701 */ 702 int 703 pqisrc_create_op_ibq(pqisrc_softstate_t *softs, 704 ib_queue_t *op_ib_q) 705 { 706 int ret = PQI_STATUS_SUCCESS; 707 gen_adm_req_iu_t admin_req; 708 gen_adm_resp_iu_t admin_resp; 709 710 DBG_FUNC("IN\n"); 711 712 memset(&admin_req, 0, sizeof(admin_req)); 713 memset(&admin_resp, 0, sizeof(admin_resp)); 714 715 admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_IQ; 716 admin_req.req_type.create_op_iq.qid = op_ib_q->q_id; 717 admin_req.req_type.create_op_iq.elem_arr_addr = op_ib_q->array_dma_addr; 718 admin_req.req_type.create_op_iq.iq_ci_addr = op_ib_q->ci_dma_addr; 719 admin_req.req_type.create_op_iq.num_elem = op_ib_q->num_elem; 720 admin_req.req_type.create_op_iq.elem_len = op_ib_q->elem_size / 16; 721 722 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 723 724 if( PQI_STATUS_SUCCESS == ret) { 725 op_ib_q->pi_register_offset =(PQISRC_PQI_REG_OFFSET + 726 admin_resp.resp_type.create_op_iq.pi_offset); 727 728 op_ib_q->pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + 729 op_ib_q->pi_register_offset); 730 } else { 731 int i = 0; 732 DBG_WARN("Error Status Decsriptors\n"); 733 for (i = 0; i < 4; i++) 734 DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]); 735 } 736 737 DBG_FUNC("OUT ret : %d\n", ret); 738 return ret; 739 } 740 741 /* 742 * subroutine used to create an operational ib queue for AIO. 743 */ 744 int 745 pqisrc_create_op_aio_ibq(pqisrc_softstate_t *softs, 746 ib_queue_t *op_aio_ib_q) 747 { 748 int ret = PQI_STATUS_SUCCESS; 749 750 DBG_FUNC("IN\n"); 751 752 ret = pqisrc_create_op_ibq(softs,op_aio_ib_q); 753 if ( PQI_STATUS_SUCCESS == ret) 754 ret = pqisrc_change_op_ibq_queue_prop(softs, 755 op_aio_ib_q, PQI_CHANGE_OP_IQ_PROP_ASSIGN_AIO); 756 757 DBG_FUNC("OUT ret : %d\n", ret); 758 return ret; 759 } 760 761 /* 762 * subroutine used to create an operational ib queue for RAID. 763 */ 764 int 765 pqisrc_create_op_raid_ibq(pqisrc_softstate_t *softs, 766 ib_queue_t *op_raid_ib_q) 767 { 768 int ret = PQI_STATUS_SUCCESS; 769 770 DBG_FUNC("IN\n"); 771 772 ret = pqisrc_create_op_ibq(softs,op_raid_ib_q); 773 774 DBG_FUNC("OUT\n"); 775 return ret; 776 } 777 778 /* 779 * Allocate and create an event queue to process supported events. 780 */ 781 int 782 pqisrc_alloc_and_create_event_queue(pqisrc_softstate_t *softs) 783 { 784 int ret = PQI_STATUS_SUCCESS; 785 uint32_t num_elem; 786 ob_queue_t *event_q = &softs->event_q; 787 788 DBG_FUNC("IN\n"); 789 790 /* 791 * Calculate memory requirements. 792 * If event queue is shared for IO response, number of 793 * elements in event queue depends on num elements in OP OB Q 794 * also. Since event queue element size (32) is more than IO 795 * response size , event queue element size need not be checked 796 * for queue size calculation. 797 */ 798 #ifdef SHARE_EVENT_QUEUE_FOR_IO 799 num_elem = MIN(softs->num_elem_per_op_obq, PQISRC_MAX_EVENT_QUEUE_ELEM_NUM); 800 #else 801 num_elem = PQISRC_MAX_EVENT_QUEUE_ELEM_NUM; 802 #endif 803 804 event_q->num_elem = num_elem; 805 event_q->elem_size = PQISRC_EVENT_Q_ELEM_SIZE_BYTES; 806 807 ret = pqisrc_allocate_and_init_outbound_q(softs, event_q, "event_queue"); 808 809 if (ret) { 810 DBG_ERR("Failed to Allocate EventQ\n"); 811 goto err_out; 812 } 813 event_q->q_id = PQI_OP_EVENT_QUEUE_ID; 814 event_q->intr_msg_num = 0; /* vector zero for event */ 815 816 ret = pqisrc_create_op_obq(softs,event_q); 817 if (ret) { 818 DBG_ERR("Failed to Create EventQ %u\n",event_q->q_id); 819 goto err_out_create; 820 } 821 event_q->created = true; 822 823 DBG_FUNC("OUT\n"); 824 return ret; 825 826 err_out_create: 827 pqisrc_destroy_event_queue(softs); 828 err_out: 829 DBG_FUNC("OUT failed %d\n", ret); 830 return PQI_STATUS_FAILURE; 831 } 832 833 /* 834 * Allocate DMA memory and create operational ib queues. 835 */ 836 int 837 pqisrc_alloc_and_create_ib_queues(pqisrc_softstate_t *softs) 838 { 839 int ret = PQI_STATUS_SUCCESS; 840 ib_queue_t *op_ib_q = NULL; 841 uint32_t ibq_id = PQI_MIN_OP_IB_QUEUE_ID; 842 uint32_t total_op_ibq = softs->num_op_raid_ibq + softs->num_op_aio_ibq; 843 int i = 0; 844 char *string = NULL; 845 846 DBG_FUNC("IN\n"); 847 848 ASSERT(softs->num_op_raid_ibq == softs->num_op_aio_ibq); 849 850 for (i = 0; i < total_op_ibq; i++) { 851 852 /* OP RAID IB Q */ 853 if (i % 2 == 0) 854 { 855 op_ib_q = &softs->op_raid_ib_q[i/2]; 856 string = "raid"; 857 } 858 else 859 { 860 op_ib_q = &softs->op_aio_ib_q[i/2]; 861 string = "aio"; 862 } 863 864 /* Allocate memory for IB queues */ 865 op_ib_q->num_elem = softs->num_elem_per_op_ibq; 866 op_ib_q->elem_size = softs->max_ibq_elem_size; 867 868 ret = pqisrc_allocate_and_init_inbound_q(softs, op_ib_q, "op_ib_queue"); 869 if (ret) { 870 DBG_ERR("Failed to Allocate Operational IBQ memory ret : %d\n", 871 ret); 872 goto err_out; 873 } 874 op_ib_q->q_id = ibq_id++; 875 876 snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "%s_ibqlock_%d", string, i); 877 ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); 878 if(ret){ 879 /* TODO: error handling */ 880 DBG_ERR("%s %d init failed\n", string, i); 881 op_ib_q->lockcreated = false; 882 goto err_lock; 883 } 884 op_ib_q->lockcreated = true; 885 886 if (i % 2 == 0) 887 ret = pqisrc_create_op_raid_ibq(softs, op_ib_q); 888 else 889 ret = pqisrc_create_op_aio_ibq(softs, op_ib_q); 890 if (ret) { 891 DBG_ERR("Failed to Create OP IBQ type=%s id=%u\n", 892 string, op_ib_q->q_id); 893 goto err_out_create; 894 } 895 op_ib_q->created = true; 896 } 897 898 DBG_FUNC("OUT\n"); 899 return ret; 900 901 err_lock: 902 err_out_create: 903 err_out: 904 pqisrc_destroy_op_ib_queues(softs); 905 DBG_FUNC("OUT failed %d\n", ret); 906 return PQI_STATUS_FAILURE; 907 } 908 909 /* 910 * Allocate DMA memory and create operational ob queues. 911 */ 912 int 913 pqisrc_alloc_and_create_ob_queues(pqisrc_softstate_t *softs) 914 { 915 int ret = PQI_STATUS_SUCCESS; 916 uint32_t obq_id = PQI_MIN_OP_OB_QUEUE_ID; 917 ob_queue_t *op_ob_q = NULL; 918 int i = 0; 919 920 DBG_FUNC("IN\n"); 921 922 /* 923 * OB Q element array should be 64 byte aligned. 924 * So the number of elements in OB Q should be multiple 925 * of 4, so that OB Queue element size (16) * num elements 926 * will be multiple of 64. 927 */ 928 929 ALIGN_BOUNDARY(softs->num_elem_per_op_obq, 4); 930 931 DBG_INIT("softs->num_op_obq %u max_obq_elem_size=%u\n",softs->num_op_obq, softs->max_obq_elem_size); 932 933 for (i = 0; i < softs->num_op_obq; i++) { 934 op_ob_q = &softs->op_ob_q[i]; 935 936 /* Allocate memory for OB queues */ 937 op_ob_q->num_elem = softs->num_elem_per_op_obq; 938 op_ob_q->elem_size = PQISRC_OP_OBQ_ELEM_SIZE_BYTES; 939 ret = pqisrc_allocate_and_init_outbound_q(softs, op_ob_q, "op_ob_queue"); 940 if (ret) { 941 DBG_ERR("Failed to Allocate Operational OBQ memory ret : %d\n", 942 ret); 943 goto err_out; 944 } 945 op_ob_q->q_id = obq_id++; 946 if(softs->share_opq_and_eventq == true) 947 op_ob_q->intr_msg_num = i; 948 else 949 op_ob_q->intr_msg_num = i + 1; /* msg num zero for event */ 950 951 ret = pqisrc_create_op_obq(softs, op_ob_q); 952 if (ret) { 953 DBG_ERR("Failed to Create OP OBQ %u\n",op_ob_q->q_id); 954 goto err_out_create; 955 } 956 op_ob_q->created = true; 957 } 958 959 DBG_FUNC("OUT\n"); 960 return ret; 961 962 err_out_create: 963 err_out: 964 pqisrc_destroy_op_ob_queues(softs); 965 DBG_FUNC("OUT failed %d\n", ret); 966 return PQI_STATUS_FAILURE; 967 } 968 969 /* 970 * Function used to create operational queues for the adapter. 971 */ 972 int 973 pqisrc_create_op_queues(pqisrc_softstate_t *softs) 974 { 975 int ret = PQI_STATUS_SUCCESS; 976 977 DBG_FUNC("IN\n"); 978 979 /* Create Operational IB queues */ 980 ret = pqisrc_alloc_and_create_ib_queues(softs); 981 if (ret) 982 goto err_out; 983 /* Create Operational OB queues */ 984 ret = pqisrc_alloc_and_create_ob_queues(softs); 985 if (ret) 986 goto err_out_obq; 987 988 /* Create Event queue */ 989 ret = pqisrc_alloc_and_create_event_queue(softs); 990 if (ret) 991 goto err_out_eventq; 992 993 DBG_FUNC("OUT\n"); 994 return ret; 995 err_out_eventq: 996 pqisrc_destroy_op_ob_queues(softs); 997 err_out_obq: 998 pqisrc_destroy_op_ib_queues(softs); 999 err_out: 1000 DBG_FUNC("OUT failed %d\n", ret); 1001 return PQI_STATUS_FAILURE; 1002 } 1003