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