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