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_INIT("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_lock; 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_lock: 368 err_q_create: 369 os_dma_mem_free(softs, &softs->admin_queue_dma_mem); 370 err_out: 371 DBG_FUNC("failed OUT\n"); 372 return ret; 373 } 374 375 /* 376 * Subroutine used to delete an operational queue. 377 */ 378 int pqisrc_delete_op_queue(pqisrc_softstate_t *softs, 379 uint32_t q_id, boolean_t ibq) 380 { 381 int ret = PQI_STATUS_SUCCESS; 382 /* Firmware doesn't support this now */ 383 384 #if 0 385 gen_adm_req_iu_t admin_req; 386 gen_adm_resp_iu_t admin_resp; 387 388 389 memset(&admin_req, 0, sizeof(admin_req)); 390 memset(&admin_resp, 0, sizeof(admin_resp)); 391 392 DBG_FUNC("IN\n"); 393 394 admin_req.req_type.create_op_iq.qid = q_id; 395 396 if (ibq) 397 admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_IQ; 398 else 399 admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_OQ; 400 401 402 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 403 404 DBG_FUNC("OUT\n"); 405 #endif 406 return ret; 407 } 408 409 /* 410 * Function used to destroy the event queue. 411 */ 412 void pqisrc_destroy_event_queue(pqisrc_softstate_t *softs) 413 { 414 DBG_FUNC("IN\n"); 415 416 if (softs->event_q.created == true) { 417 int ret = PQI_STATUS_SUCCESS; 418 ret = pqisrc_delete_op_queue(softs, softs->event_q.q_id, false); 419 if (ret) { 420 DBG_ERR("Failed to Delete Event Q %d\n", softs->event_q.q_id); 421 } 422 softs->event_q.created = false; 423 } 424 425 /* Free the memory */ 426 os_dma_mem_free(softs, &softs->event_q_dma_mem); 427 428 DBG_FUNC("OUT\n"); 429 } 430 431 /* 432 * Function used to destroy operational ib queues. 433 */ 434 void pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs) 435 { 436 int ret = PQI_STATUS_SUCCESS; 437 ib_queue_t *op_ib_q = NULL; 438 int i; 439 440 DBG_FUNC("IN\n"); 441 442 for (i = 0; i < softs->num_op_raid_ibq; i++) { 443 /* OP RAID IB Q */ 444 op_ib_q = &softs->op_raid_ib_q[i]; 445 if (op_ib_q->created == true) { 446 ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, true); 447 if (ret) { 448 DBG_ERR("Failed to Delete Raid IB Q %d\n",op_ib_q->q_id); 449 } 450 op_ib_q->created = false; 451 } 452 453 if(op_ib_q->lockcreated==true){ 454 OS_UNINIT_PQILOCK(&op_ib_q->lock); 455 op_ib_q->lockcreated = false; 456 } 457 458 /* OP AIO IB Q */ 459 op_ib_q = &softs->op_aio_ib_q[i]; 460 if (op_ib_q->created == true) { 461 ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, true); 462 if (ret) { 463 DBG_ERR("Failed to Delete AIO IB Q %d\n",op_ib_q->q_id); 464 } 465 op_ib_q->created = false; 466 } 467 468 if(op_ib_q->lockcreated==true){ 469 OS_UNINIT_PQILOCK(&op_ib_q->lock); 470 op_ib_q->lockcreated = false; 471 } 472 } 473 474 /* Free the memory */ 475 os_dma_mem_free(softs, &softs->op_ibq_dma_mem); 476 DBG_FUNC("OUT\n"); 477 } 478 479 /* 480 * Function used to destroy operational ob queues. 481 */ 482 void pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) 483 { 484 int ret = PQI_STATUS_SUCCESS; 485 int i; 486 487 DBG_FUNC("IN\n"); 488 489 for (i = 0; i < softs->num_op_obq; i++) { 490 ob_queue_t *op_ob_q = NULL; 491 op_ob_q = &softs->op_ob_q[i]; 492 if (op_ob_q->created == true) { 493 ret = pqisrc_delete_op_queue(softs, op_ob_q->q_id, false); 494 if (ret) { 495 DBG_ERR("Failed to Delete OB Q %d\n",op_ob_q->q_id); 496 } 497 op_ob_q->created = false; 498 } 499 } 500 501 /* Free the memory */ 502 os_dma_mem_free(softs, &softs->op_obq_dma_mem); 503 DBG_FUNC("OUT\n"); 504 } 505 506 /* 507 * Function used to destroy an admin queue. 508 */ 509 int pqisrc_destroy_admin_queue(pqisrc_softstate_t *softs) 510 { 511 int ret = PQI_STATUS_SUCCESS; 512 513 DBG_FUNC("IN\n"); 514 #if 0 515 ret = pqisrc_create_delete_adminq(softs, 516 PQI_ADMIN_QUEUE_CONF_FUNC_DEL_Q_PAIR); 517 #endif 518 os_dma_mem_free(softs, &softs->admin_queue_dma_mem); 519 520 DBG_FUNC("OUT\n"); 521 return ret; 522 } 523 524 /* 525 * Function used to change operational ib queue properties. 526 */ 527 int pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *softs, 528 ib_queue_t *op_ib_q, uint32_t prop) 529 { 530 int ret = PQI_STATUS_SUCCESS;; 531 gen_adm_req_iu_t admin_req; 532 gen_adm_resp_iu_t admin_resp; 533 534 memset(&admin_req, 0, sizeof(admin_req)); 535 memset(&admin_resp, 0, sizeof(admin_resp)); 536 537 DBG_FUNC("IN\n"); 538 539 admin_req.fn_code = PQI_FUNCTION_CHANGE_OPERATIONAL_IQ_PROP; 540 admin_req.req_type.change_op_iq_prop.qid = op_ib_q->q_id; 541 admin_req.req_type.change_op_iq_prop.vend_specific = prop; 542 543 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 544 545 DBG_FUNC("OUT\n"); 546 return ret; 547 } 548 549 /* 550 * Function used to create an operational ob queue. 551 */ 552 int pqisrc_create_op_obq(pqisrc_softstate_t *softs, 553 ob_queue_t *op_ob_q) 554 { 555 int ret = PQI_STATUS_SUCCESS;; 556 gen_adm_req_iu_t admin_req; 557 gen_adm_resp_iu_t admin_resp; 558 559 DBG_FUNC("IN\n"); 560 561 memset(&admin_req, 0, sizeof(admin_req)); 562 memset(&admin_resp, 0, sizeof(admin_resp)); 563 564 admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_OQ; 565 admin_req.req_type.create_op_oq.qid = op_ob_q->q_id; 566 admin_req.req_type.create_op_oq.intr_msg_num = op_ob_q->intr_msg_num; 567 admin_req.req_type.create_op_oq.elem_arr_addr = op_ob_q->array_dma_addr; 568 admin_req.req_type.create_op_oq.ob_pi_addr = op_ob_q->pi_dma_addr; 569 admin_req.req_type.create_op_oq.num_elem = op_ob_q->num_elem; 570 admin_req.req_type.create_op_oq.elem_len = op_ob_q->elem_size / 16; 571 572 DBG_INFO("admin_req.req_type.create_op_oq.qid : %x\n",admin_req.req_type.create_op_oq.qid); 573 DBG_INFO("admin_req.req_type.create_op_oq.intr_msg_num : %x\n", admin_req.req_type.create_op_oq.intr_msg_num ); 574 575 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 576 if( PQI_STATUS_SUCCESS == ret) { 577 op_ob_q->ci_register_offset = (PQISRC_PQI_REG_OFFSET + 578 admin_resp.resp_type.create_op_oq.ci_offset); 579 op_ob_q->ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + 580 op_ob_q->ci_register_offset); 581 } else { 582 int i = 0; 583 DBG_WARN("Error Status Descriptors\n"); 584 for(i = 0; i < 4;i++) 585 DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]); 586 } 587 588 DBG_FUNC("OUT ret : %d\n", ret); 589 590 return ret; 591 } 592 593 /* 594 * Function used to create an operational ib queue. 595 */ 596 int pqisrc_create_op_ibq(pqisrc_softstate_t *softs, 597 ib_queue_t *op_ib_q) 598 { 599 int ret = PQI_STATUS_SUCCESS;; 600 gen_adm_req_iu_t admin_req; 601 gen_adm_resp_iu_t admin_resp; 602 603 DBG_FUNC("IN\n"); 604 605 memset(&admin_req, 0, sizeof(admin_req)); 606 memset(&admin_resp, 0, sizeof(admin_resp)); 607 608 admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_IQ; 609 admin_req.req_type.create_op_iq.qid = op_ib_q->q_id; 610 admin_req.req_type.create_op_iq.elem_arr_addr = op_ib_q->array_dma_addr; 611 admin_req.req_type.create_op_iq.iq_ci_addr = op_ib_q->ci_dma_addr; 612 admin_req.req_type.create_op_iq.num_elem = op_ib_q->num_elem; 613 admin_req.req_type.create_op_iq.elem_len = op_ib_q->elem_size / 16; 614 615 ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); 616 617 if( PQI_STATUS_SUCCESS == ret) { 618 op_ib_q->pi_register_offset =(PQISRC_PQI_REG_OFFSET + 619 admin_resp.resp_type.create_op_iq.pi_offset); 620 621 op_ib_q->pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + 622 op_ib_q->pi_register_offset); 623 } else { 624 int i = 0; 625 DBG_WARN("Error Status Decsriptors\n"); 626 for(i = 0; i < 4;i++) 627 DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]); 628 } 629 630 DBG_FUNC("OUT ret : %d\n", ret); 631 return ret; 632 } 633 634 /* 635 * subroutine used to create an operational ib queue for AIO. 636 */ 637 int pqisrc_create_op_aio_ibq(pqisrc_softstate_t *softs, 638 ib_queue_t *op_aio_ib_q) 639 { 640 int ret = PQI_STATUS_SUCCESS; 641 642 DBG_FUNC("IN\n"); 643 644 ret = pqisrc_create_op_ibq(softs,op_aio_ib_q); 645 if ( PQI_STATUS_SUCCESS == ret) 646 ret = pqisrc_change_op_ibq_queue_prop(softs, 647 op_aio_ib_q, PQI_CHANGE_OP_IQ_PROP_ASSIGN_AIO); 648 649 DBG_FUNC("OUT ret : %d\n", ret); 650 return ret; 651 } 652 653 /* 654 * subroutine used to create an operational ib queue for RAID. 655 */ 656 int pqisrc_create_op_raid_ibq(pqisrc_softstate_t *softs, 657 ib_queue_t *op_raid_ib_q) 658 { 659 int ret = PQI_STATUS_SUCCESS;; 660 661 DBG_FUNC("IN\n"); 662 663 ret = pqisrc_create_op_ibq(softs,op_raid_ib_q); 664 665 DBG_FUNC("OUT\n"); 666 return ret; 667 } 668 669 /* 670 * Allocate and create an event queue to process supported events. 671 */ 672 int pqisrc_alloc_and_create_event_queue(pqisrc_softstate_t *softs) 673 { 674 int ret = PQI_STATUS_SUCCESS; 675 uint32_t alloc_size = 0; 676 uint32_t num_elem; 677 char *virt_addr = NULL; 678 dma_addr_t dma_addr = 0; 679 uint32_t event_q_pi_dma_start_offset = 0; 680 uint32_t event_q_pi_virt_start_offset = 0; 681 char *event_q_pi_virt_start_addr = NULL; 682 ob_queue_t *event_q = NULL; 683 684 685 DBG_FUNC("IN\n"); 686 687 /* 688 * Calculate memory requirements. 689 * If event queue is shared for IO response, number of 690 * elements in event queue depends on num elements in OP OB Q 691 * also. Since event queue element size (32) is more than IO 692 * response size , event queue element size need not be checked 693 * for queue size calculation. 694 */ 695 #ifdef SHARE_EVENT_QUEUE_FOR_IO 696 num_elem = MIN(softs->num_elem_per_op_obq, PQISRC_NUM_EVENT_Q_ELEM); 697 #else 698 num_elem = PQISRC_NUM_EVENT_Q_ELEM; 699 #endif 700 701 alloc_size = num_elem * PQISRC_EVENT_Q_ELEM_SIZE; 702 event_q_pi_dma_start_offset = alloc_size; 703 event_q_pi_virt_start_offset = alloc_size; 704 alloc_size += sizeof(uint32_t); /*For IBQ CI*/ 705 706 /* Allocate memory for event queues */ 707 softs->event_q_dma_mem.tag = "event_queue"; 708 softs->event_q_dma_mem.size = alloc_size; 709 softs->event_q_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN; 710 ret = os_dma_mem_alloc(softs, &softs->event_q_dma_mem); 711 if (ret) { 712 DBG_ERR("Failed to Allocate Event Q ret : %d\n" 713 , ret); 714 goto err_out; 715 } 716 717 /* Set up the address */ 718 virt_addr = softs->event_q_dma_mem.virt_addr; 719 dma_addr = softs->event_q_dma_mem.dma_addr; 720 event_q_pi_dma_start_offset += dma_addr; 721 event_q_pi_virt_start_addr = virt_addr + event_q_pi_virt_start_offset; 722 723 event_q = &softs->event_q; 724 ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); 725 FILL_QUEUE_ARRAY_ADDR(event_q,virt_addr,dma_addr); 726 event_q->q_id = PQI_OP_EVENT_QUEUE_ID; 727 event_q->num_elem = num_elem; 728 event_q->elem_size = PQISRC_EVENT_Q_ELEM_SIZE; 729 event_q->pi_dma_addr = event_q_pi_dma_start_offset; 730 event_q->pi_virt_addr = (uint32_t *)event_q_pi_virt_start_addr; 731 event_q->intr_msg_num = 0; /* vector zero for event */ 732 ASSERT(!(event_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4)); 733 734 ret = pqisrc_create_op_obq(softs,event_q); 735 if (ret) { 736 DBG_ERR("Failed to Create EventQ %d\n",event_q->q_id); 737 goto err_out_create; 738 } 739 event_q->created = true; 740 741 DBG_FUNC("OUT\n"); 742 return ret; 743 744 err_out_create: 745 pqisrc_destroy_event_queue(softs); 746 err_out: 747 DBG_FUNC("OUT failed %d\n", ret); 748 return PQI_STATUS_FAILURE; 749 } 750 751 /* 752 * Allocate DMA memory and create operational ib queues. 753 */ 754 int pqisrc_alloc_and_create_ib_queues(pqisrc_softstate_t *softs) 755 { 756 int ret = PQI_STATUS_SUCCESS; 757 uint32_t alloc_size = 0; 758 char *virt_addr = NULL; 759 dma_addr_t dma_addr = 0; 760 uint32_t ibq_size = 0; 761 uint32_t ib_ci_dma_start_offset = 0; 762 char *ib_ci_virt_start_addr = NULL; 763 uint32_t ib_ci_virt_start_offset = 0; 764 uint32_t ibq_id = PQI_MIN_OP_IB_QUEUE_ID; 765 ib_queue_t *op_ib_q = NULL; 766 uint32_t num_op_ibq = softs->num_op_raid_ibq + 767 softs->num_op_aio_ibq; 768 int i = 0; 769 770 DBG_FUNC("IN\n"); 771 772 /* Calculate memory requirements */ 773 ibq_size = softs->num_elem_per_op_ibq * softs->ibq_elem_size; 774 alloc_size = num_op_ibq * ibq_size; 775 /* CI indexes starts after Queue element array */ 776 ib_ci_dma_start_offset = alloc_size; 777 ib_ci_virt_start_offset = alloc_size; 778 alloc_size += num_op_ibq * sizeof(uint32_t); /*For IBQ CI*/ 779 780 /* Allocate memory for IB queues */ 781 softs->op_ibq_dma_mem.tag = "op_ib_queue"; 782 softs->op_ibq_dma_mem.size = alloc_size; 783 softs->op_ibq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN; 784 ret = os_dma_mem_alloc(softs, &softs->op_ibq_dma_mem); 785 if (ret) { 786 DBG_ERR("Failed to Allocate Operational IBQ memory ret : %d\n", 787 ret); 788 goto err_out; 789 } 790 791 /* Set up the address */ 792 virt_addr = softs->op_ibq_dma_mem.virt_addr; 793 dma_addr = softs->op_ibq_dma_mem.dma_addr; 794 ib_ci_dma_start_offset += dma_addr; 795 ib_ci_virt_start_addr = virt_addr + ib_ci_virt_start_offset; 796 797 ASSERT(softs->num_op_raid_ibq == softs->num_op_aio_ibq); 798 799 for (i = 0; i < softs->num_op_raid_ibq; i++) { 800 /* OP RAID IB Q */ 801 op_ib_q = &softs->op_raid_ib_q[i]; 802 ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); 803 FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr); 804 op_ib_q->q_id = ibq_id++; 805 806 snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "raid_ibqlock%d", i); 807 ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); 808 if(ret){ 809 DBG_ERR("raid_ibqlock %d init failed\n", i); 810 op_ib_q->lockcreated = false; 811 goto err_lock; 812 } 813 op_ib_q->lockcreated = true; 814 op_ib_q->num_elem = softs->num_elem_per_op_ibq; 815 op_ib_q->elem_size = softs->ibq_elem_size; 816 op_ib_q->ci_dma_addr = ib_ci_dma_start_offset + 817 (2 * i * sizeof(uint32_t)); 818 op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr + 819 (2 * i * sizeof(uint32_t))); 820 ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4)); 821 ret = pqisrc_create_op_raid_ibq(softs, op_ib_q); 822 if (ret) { 823 DBG_ERR("[ %s ] Failed to Create OP Raid IBQ %d\n", 824 __func__, op_ib_q->q_id); 825 goto err_out_create; 826 } 827 op_ib_q->created = true; 828 829 /* OP AIO IB Q */ 830 virt_addr += ibq_size; 831 dma_addr += ibq_size; 832 op_ib_q = &softs->op_aio_ib_q[i]; 833 ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); 834 FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr); 835 op_ib_q->q_id = ibq_id++; 836 snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "aio_ibqlock%d", i); 837 ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); 838 if(ret){ 839 DBG_ERR("aio_ibqlock %d init failed\n", i); 840 op_ib_q->lockcreated = false; 841 goto err_lock; 842 } 843 op_ib_q->lockcreated = true; 844 op_ib_q->num_elem = softs->num_elem_per_op_ibq; 845 op_ib_q->elem_size = softs->ibq_elem_size; 846 op_ib_q->ci_dma_addr = ib_ci_dma_start_offset + 847 (((2 * i) + 1) * sizeof(uint32_t)); 848 op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr + 849 (((2 * i) + 1) * sizeof(uint32_t))); 850 ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4)); 851 ret = pqisrc_create_op_aio_ibq(softs, op_ib_q); 852 if (ret) { 853 DBG_ERR("Failed to Create OP AIO IBQ %d\n",op_ib_q->q_id); 854 goto err_out_create; 855 } 856 op_ib_q->created = true; 857 858 virt_addr += ibq_size; 859 dma_addr += ibq_size; 860 } 861 862 DBG_FUNC("OUT\n"); 863 return ret; 864 865 err_lock: 866 err_out_create: 867 pqisrc_destroy_op_ib_queues(softs); 868 err_out: 869 DBG_FUNC("OUT failed %d\n", ret); 870 return PQI_STATUS_FAILURE; 871 } 872 873 /* 874 * Allocate DMA memory and create operational ob queues. 875 */ 876 int pqisrc_alloc_and_create_ob_queues(pqisrc_softstate_t *softs) 877 { 878 int ret = PQI_STATUS_SUCCESS; 879 uint32_t alloc_size = 0; 880 char *virt_addr = NULL; 881 dma_addr_t dma_addr = 0; 882 uint32_t obq_size = 0; 883 uint32_t ob_pi_dma_start_offset = 0; 884 uint32_t ob_pi_virt_start_offset = 0; 885 char *ob_pi_virt_start_addr = NULL; 886 uint32_t obq_id = PQI_MIN_OP_OB_QUEUE_ID; 887 ob_queue_t *op_ob_q = NULL; 888 uint32_t num_op_obq = softs->num_op_obq; 889 int i = 0; 890 891 DBG_FUNC("IN\n"); 892 893 /* 894 * OB Q element array should be 64 byte aligned. 895 * So the number of elements in OB Q should be multiple 896 * of 4, so that OB Queue element size (16) * num elements 897 * will be multiple of 64. 898 */ 899 900 ALIGN_BOUNDARY(softs->num_elem_per_op_obq, 4); 901 obq_size = softs->num_elem_per_op_obq * softs->obq_elem_size; 902 alloc_size += num_op_obq * obq_size; 903 /* PI indexes starts after Queue element array */ 904 ob_pi_dma_start_offset = alloc_size; 905 ob_pi_virt_start_offset = alloc_size; 906 alloc_size += num_op_obq * sizeof(uint32_t); /*For OBQ PI*/ 907 908 /* Allocate memory for OB queues */ 909 softs->op_obq_dma_mem.tag = "op_ob_queue"; 910 softs->op_obq_dma_mem.size = alloc_size; 911 softs->op_obq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN; 912 ret = os_dma_mem_alloc(softs, &softs->op_obq_dma_mem); 913 if (ret) { 914 DBG_ERR("Failed to Allocate Operational OBQ memory ret : %d\n", 915 ret); 916 goto err_out; 917 } 918 919 /* Set up the address */ 920 virt_addr = softs->op_obq_dma_mem.virt_addr; 921 dma_addr = softs->op_obq_dma_mem.dma_addr; 922 ob_pi_dma_start_offset += dma_addr; 923 ob_pi_virt_start_addr = virt_addr + ob_pi_virt_start_offset; 924 925 DBG_INFO("softs->num_op_obq %d\n",softs->num_op_obq); 926 927 for (i = 0; i < softs->num_op_obq; i++) { 928 op_ob_q = &softs->op_ob_q[i]; 929 ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); 930 FILL_QUEUE_ARRAY_ADDR(op_ob_q,virt_addr,dma_addr); 931 op_ob_q->q_id = obq_id++; 932 if(softs->share_opq_and_eventq == true) 933 op_ob_q->intr_msg_num = i; 934 else 935 op_ob_q->intr_msg_num = i + 1; /* msg num zero for event */ 936 op_ob_q->num_elem = softs->num_elem_per_op_obq; 937 op_ob_q->elem_size = softs->obq_elem_size; 938 op_ob_q->pi_dma_addr = ob_pi_dma_start_offset + 939 (i * sizeof(uint32_t)); 940 op_ob_q->pi_virt_addr = (uint32_t*)(ob_pi_virt_start_addr + 941 (i * sizeof(uint32_t))); 942 ASSERT(!(op_ob_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4)); 943 944 ret = pqisrc_create_op_obq(softs,op_ob_q); 945 if (ret) { 946 DBG_ERR("Failed to Create OP OBQ %d\n",op_ob_q->q_id); 947 goto err_out_create; 948 } 949 op_ob_q->created = true; 950 virt_addr += obq_size; 951 dma_addr += obq_size; 952 } 953 954 DBG_FUNC("OUT\n"); 955 return ret; 956 957 err_out_create: 958 pqisrc_destroy_op_ob_queues(softs); 959 err_out: 960 DBG_FUNC("OUT failed %d\n", ret); 961 return PQI_STATUS_FAILURE; 962 } 963 964 /* 965 * Function used to create operational queues for the adapter. 966 */ 967 int pqisrc_create_op_queues(pqisrc_softstate_t *softs) 968 { 969 int ret = PQI_STATUS_SUCCESS; 970 971 DBG_FUNC("IN\n"); 972 973 /* Create Operational IB queues */ 974 ret = pqisrc_alloc_and_create_ib_queues(softs); 975 if (ret) 976 goto err_out; 977 /* Create Operational OB queues */ 978 ret = pqisrc_alloc_and_create_ob_queues(softs); 979 if (ret) 980 goto err_out_obq; 981 982 /* Create Event queue */ 983 ret = pqisrc_alloc_and_create_event_queue(softs); 984 if (ret) 985 goto err_out_eventq; 986 987 DBG_FUNC("OUT\n"); 988 return ret; 989 err_out_eventq: 990 pqisrc_destroy_op_ob_queues(softs); 991 err_out_obq: 992 pqisrc_destroy_op_ib_queues(softs); 993 err_out: 994 DBG_FUNC("OUT failed %d\n", ret); 995 return PQI_STATUS_FAILURE; 996 } 997