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