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