1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Source file containing Queue handling functions 29 * 30 */ 31 32 #include <oce_impl.h> 33 34 int oce_destroy_q(struct oce_dev *oce, struct oce_mbx *mbx, size_t req_size, 35 enum qtype qtype); 36 /* MAil box Queue functions */ 37 struct oce_mq * 38 oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len); 39 40 /* event queue handling */ 41 struct oce_eq * 42 oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size, 43 uint32_t eq_delay); 44 45 /* completion queue handling */ 46 struct oce_cq * 47 oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, 48 uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, 49 boolean_t nodelay, uint32_t ncoalesce); 50 51 52 /* Tx WQ functions */ 53 static struct oce_wq *oce_wq_init(struct oce_dev *dev, uint32_t q_len, 54 int wq_type); 55 static void oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq); 56 static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq); 57 static void oce_wq_del(struct oce_dev *dev, struct oce_wq *wq); 58 /* Rx Queue functions */ 59 static struct oce_rq *oce_rq_init(struct oce_dev *dev, uint32_t q_len, 60 uint32_t frag_size, uint32_t mtu, 61 boolean_t rss); 62 static void oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq); 63 static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq); 64 static void oce_rq_del(struct oce_dev *dev, struct oce_rq *rq); 65 66 /* 67 * function to create an event queue 68 * 69 * dev - software handle to the device 70 * eqcfg - pointer to a config structure containg the eq parameters 71 * 72 * return pointer to EQ; NULL on failure 73 */ 74 struct oce_eq * 75 oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size, 76 uint32_t eq_delay) 77 { 78 struct oce_eq *eq; 79 struct oce_mbx mbx; 80 struct mbx_create_common_eq *fwcmd; 81 int ret = 0; 82 83 /* allocate an eq */ 84 eq = kmem_zalloc(sizeof (struct oce_eq), KM_NOSLEEP); 85 86 if (eq == NULL) { 87 return (NULL); 88 } 89 90 bzero(&mbx, sizeof (struct oce_mbx)); 91 /* allocate mbx */ 92 fwcmd = (struct mbx_create_common_eq *)&mbx.payload; 93 94 eq->ring = create_ring_buffer(dev, q_len, 95 item_size, DDI_DMA_CONSISTENT); 96 97 if (eq->ring == NULL) { 98 oce_log(dev, CE_WARN, MOD_CONFIG, 99 "EQ ring alloc failed:0x%p", 100 (void *)eq->ring); 101 kmem_free(eq, sizeof (struct oce_eq)); 102 return (NULL); 103 } 104 105 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 106 MBX_SUBSYSTEM_COMMON, 107 OPCODE_CREATE_COMMON_EQ, MBX_TIMEOUT_SEC, 108 sizeof (struct mbx_create_common_eq)); 109 110 fwcmd->params.req.num_pages = eq->ring->dbuf->num_pages; 111 oce_page_list(eq->ring->dbuf, &fwcmd->params.req.pages[0], 112 eq->ring->dbuf->num_pages); 113 114 /* dw 0 */ 115 fwcmd->params.req.eq_ctx.size = (item_size == 4) ? 0 : 1; 116 fwcmd->params.req.eq_ctx.valid = 1; 117 /* dw 1 */ 118 fwcmd->params.req.eq_ctx.armed = 0; 119 fwcmd->params.req.eq_ctx.pd = 0; 120 fwcmd->params.req.eq_ctx.count = OCE_LOG2(q_len/256); 121 122 /* dw 2 */ 123 fwcmd->params.req.eq_ctx.function = dev->fn; 124 fwcmd->params.req.eq_ctx.nodelay = 0; 125 fwcmd->params.req.eq_ctx.phase = 0; 126 /* todo: calculate multiplier from max min and cur */ 127 fwcmd->params.req.eq_ctx.delay_mult = eq_delay; 128 129 /* fill rest of mbx */ 130 mbx.u0.s.embedded = 1; 131 mbx.payload_length = sizeof (struct mbx_create_common_eq); 132 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 133 134 /* now post the command */ 135 ret = oce_mbox_post(dev, &mbx, NULL); 136 137 if (ret != 0) { 138 oce_log(dev, CE_WARN, MOD_CONFIG, 139 "EQ create failed: %d", ret); 140 destroy_ring_buffer(dev, eq->ring); 141 kmem_free(eq, sizeof (struct oce_eq)); 142 return (NULL); 143 } 144 145 /* interpret the response */ 146 eq->eq_id = LE_16(fwcmd->params.rsp.eq_id); 147 eq->eq_cfg.q_len = q_len; 148 eq->eq_cfg.item_size = item_size; 149 eq->eq_cfg.cur_eqd = (uint8_t)eq_delay; 150 eq->parent = (void *)dev; 151 atomic_inc_32(&dev->neqs); 152 oce_log(dev, CE_NOTE, MOD_CONFIG, 153 "EQ created, eq=0x%p eq_id=0x%x", (void *)eq, eq->eq_id); 154 /* Save the eq pointer */ 155 return (eq); 156 } /* oce_eq_create */ 157 158 /* 159 * function to delete an event queue 160 * 161 * dev - software handle to the device 162 * eq - handle to the eq to be deleted 163 * 164 * return 0=>success, failure otherwise 165 */ 166 void 167 oce_eq_del(struct oce_dev *dev, struct oce_eq *eq) 168 { 169 struct oce_mbx mbx; 170 struct mbx_destroy_common_eq *fwcmd; 171 172 /* drain the residual events */ 173 oce_drain_eq(eq); 174 175 /* destroy the ring */ 176 destroy_ring_buffer(dev, eq->ring); 177 eq->ring = NULL; 178 179 /* send a command to delete the EQ */ 180 fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload; 181 fwcmd->params.req.id = eq->eq_id; 182 (void) oce_destroy_q(dev, &mbx, 183 sizeof (struct mbx_destroy_common_eq), 184 QTYPE_EQ); 185 kmem_free(eq, sizeof (struct oce_eq)); 186 atomic_dec_32(&dev->neqs); 187 } 188 189 /* 190 * function to create a completion queue 191 * 192 * dev - software handle to the device 193 * eq - optional eq to be associated with to the cq 194 * cqcfg - configuration for this queue 195 * 196 * return pointer to the cq created. NULL on failure 197 */ 198 struct oce_cq * 199 oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len, 200 uint32_t item_size, boolean_t sol_event, boolean_t is_eventable, 201 boolean_t nodelay, uint32_t ncoalesce) 202 { 203 struct oce_cq *cq = NULL; 204 struct oce_mbx mbx; 205 struct mbx_create_common_cq *fwcmd; 206 int ret = 0; 207 208 /* create cq */ 209 cq = kmem_zalloc(sizeof (struct oce_cq), KM_NOSLEEP); 210 if (cq == NULL) { 211 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", 212 "CQ allocation failed"); 213 return (NULL); 214 } 215 216 /* create the ring buffer for this queue */ 217 cq->ring = create_ring_buffer(dev, q_len, 218 item_size, DDI_DMA_CONSISTENT); 219 if (cq->ring == NULL) { 220 oce_log(dev, CE_WARN, MOD_CONFIG, 221 "CQ ring alloc failed:0x%p", 222 (void *)cq->ring); 223 kmem_free(cq, sizeof (struct oce_cq)); 224 return (NULL); 225 } 226 /* initialize mailbox */ 227 bzero(&mbx, sizeof (struct oce_mbx)); 228 fwcmd = (struct mbx_create_common_cq *)&mbx.payload; 229 230 /* fill the command header */ 231 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 232 MBX_SUBSYSTEM_COMMON, 233 OPCODE_CREATE_COMMON_CQ, MBX_TIMEOUT_SEC, 234 sizeof (struct mbx_create_common_cq)); 235 236 /* fill command context */ 237 /* dw0 */ 238 fwcmd->params.req.cq_ctx.eventable = is_eventable; 239 fwcmd->params.req.cq_ctx.sol_event = sol_event; 240 fwcmd->params.req.cq_ctx.valid = 1; 241 fwcmd->params.req.cq_ctx.count = OCE_LOG2(q_len/256); 242 fwcmd->params.req.cq_ctx.nodelay = nodelay; 243 fwcmd->params.req.cq_ctx.coalesce_wm = ncoalesce; 244 245 /* dw1 */ 246 fwcmd->params.req.cq_ctx.armed = B_FALSE; 247 fwcmd->params.req.cq_ctx.eq_id = eq->eq_id; 248 fwcmd->params.req.cq_ctx.pd = 0; 249 /* dw2 */ 250 fwcmd->params.req.cq_ctx.function = dev->fn; 251 252 /* fill the rest of the command */ 253 fwcmd->params.req.num_pages = cq->ring->dbuf->num_pages; 254 oce_page_list(cq->ring->dbuf, &fwcmd->params.req.pages[0], 255 cq->ring->dbuf->num_pages); 256 257 /* fill rest of mbx */ 258 mbx.u0.s.embedded = 1; 259 mbx.payload_length = sizeof (struct mbx_create_common_cq); 260 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 261 262 /* now send the mail box */ 263 ret = oce_mbox_post(dev, &mbx, NULL); 264 265 if (ret != 0) { 266 oce_log(dev, CE_WARN, MOD_CONFIG, 267 "CQ create failed: 0x%x", ret); 268 destroy_ring_buffer(dev, cq->ring); 269 kmem_free(cq, sizeof (struct oce_cq)); 270 return (NULL); 271 } 272 273 cq->parent = dev; 274 cq->eq = eq; /* eq array index */ 275 cq->cq_cfg.q_len = q_len; 276 cq->cq_cfg.item_size = item_size; 277 cq->cq_cfg.sol_eventable = (uint8_t)sol_event; 278 cq->cq_cfg.nodelay = (uint8_t)nodelay; 279 /* interpret the response */ 280 cq->cq_id = LE_16(fwcmd->params.rsp.cq_id); 281 dev->cq[cq->cq_id] = cq; 282 atomic_inc_32(&eq->ref_count); 283 return (cq); 284 } /* oce_cq_create */ 285 286 /* 287 * function to delete a completion queue 288 * 289 * dev - software handle to the device 290 * cq - handle to the CQ to delete 291 * 292 * return none 293 */ 294 static void 295 oce_cq_del(struct oce_dev *dev, struct oce_cq *cq) 296 { 297 struct oce_mbx mbx; 298 struct mbx_destroy_common_cq *fwcmd; 299 300 /* destroy the ring */ 301 destroy_ring_buffer(dev, cq->ring); 302 cq->ring = NULL; 303 304 bzero(&mbx, sizeof (struct oce_mbx)); 305 /* send a command to delete the CQ */ 306 fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload; 307 fwcmd->params.req.id = cq->cq_id; 308 (void) oce_destroy_q(dev, &mbx, 309 sizeof (struct mbx_destroy_common_cq), 310 QTYPE_CQ); 311 312 /* Reset the handler */ 313 cq->cq_handler = NULL; 314 dev->cq[cq->cq_id] = NULL; 315 atomic_dec_32(&cq->eq->ref_count); 316 mutex_destroy(&cq->lock); 317 318 /* release the eq */ 319 kmem_free(cq, sizeof (struct oce_cq)); 320 } /* oce_cq_del */ 321 322 /* 323 * function to create an MQ 324 * 325 * dev - software handle to the device 326 * eq - the EQ to associate with the MQ for event notification 327 * q_len - the number of entries to create in the MQ 328 * 329 * return pointer to the created MQ, failure otherwise 330 */ 331 struct oce_mq * 332 oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len) 333 { 334 struct oce_mbx mbx; 335 struct mbx_create_common_mq *fwcmd; 336 struct oce_mq *mq = NULL; 337 int ret = 0; 338 struct oce_cq *cq; 339 340 /* Create the Completion Q */ 341 cq = oce_cq_create(dev, eq, CQ_LEN_256, 342 sizeof (struct oce_mq_cqe), 343 B_FALSE, B_TRUE, B_TRUE, 0); 344 if (cq == NULL) { 345 return (NULL); 346 } 347 348 349 /* allocate the mq */ 350 mq = kmem_zalloc(sizeof (struct oce_mq), KM_NOSLEEP); 351 352 if (mq == NULL) { 353 goto mq_alloc_fail; 354 } 355 356 bzero(&mbx, sizeof (struct oce_mbx)); 357 /* allocate mbx */ 358 fwcmd = (struct mbx_create_common_mq *)&mbx.payload; 359 360 /* create the ring buffer for this queue */ 361 mq->ring = create_ring_buffer(dev, q_len, 362 sizeof (struct oce_mbx), DDI_DMA_CONSISTENT); 363 if (mq->ring == NULL) { 364 oce_log(dev, CE_WARN, MOD_CONFIG, 365 "MQ ring alloc failed:0x%p", 366 (void *)mq->ring); 367 goto mq_ring_alloc; 368 } 369 370 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 371 MBX_SUBSYSTEM_COMMON, 372 OPCODE_CREATE_COMMON_MQ, MBX_TIMEOUT_SEC, 373 sizeof (struct mbx_create_common_mq)); 374 375 fwcmd->params.req.num_pages = mq->ring->dbuf->num_pages; 376 oce_page_list(mq->ring->dbuf, fwcmd->params.req.pages, 377 mq->ring->dbuf->num_pages); 378 fwcmd->params.req.context.u0.s.cq_id = cq->cq_id; 379 fwcmd->params.req.context.u0.s.ring_size = 380 OCE_LOG2(q_len) + 1; 381 fwcmd->params.req.context.u0.s.valid = 1; 382 fwcmd->params.req.context.u0.s.fid = dev->fn; 383 384 /* fill rest of mbx */ 385 mbx.u0.s.embedded = 1; 386 mbx.payload_length = sizeof (struct mbx_create_common_mq); 387 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 388 389 /* now send the mail box */ 390 ret = oce_mbox_post(dev, &mbx, NULL); 391 if (ret != DDI_SUCCESS) { 392 oce_log(dev, CE_WARN, MOD_CONFIG, 393 "MQ create failed: 0x%x", ret); 394 goto mq_fail; 395 } 396 397 /* interpret the response */ 398 mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); 399 mq->cq = cq; 400 mq->cfg.q_len = (uint8_t)q_len; 401 mq->cfg.eqd = 0; 402 403 /* fill rest of the mq */ 404 mq->parent = dev; 405 406 /* set the MQCQ handlers */ 407 cq->cq_handler = oce_drain_mq_cq; 408 cq->cb_arg = (void *)mq; 409 mutex_init(&mq->lock, NULL, MUTEX_DRIVER, 410 DDI_INTR_PRI(dev->intr_pri)); 411 return (mq); 412 413 mq_fail: 414 destroy_ring_buffer(dev, mq->ring); 415 mq_ring_alloc: 416 kmem_free(mq, sizeof (struct oce_mq)); 417 mq_alloc_fail: 418 oce_cq_del(dev, cq); 419 return (NULL); 420 } /* oce_mq_create */ 421 422 /* 423 * function to delete an MQ 424 * 425 * dev - software handle to the device 426 * mq - pointer to the MQ to delete 427 * 428 * return none 429 */ 430 static void 431 oce_mq_del(struct oce_dev *dev, struct oce_mq *mq) 432 { 433 struct oce_mbx mbx; 434 struct mbx_destroy_common_mq *fwcmd; 435 436 /* destroy the ring */ 437 destroy_ring_buffer(dev, mq->ring); 438 mq->ring = NULL; 439 bzero(&mbx, sizeof (struct oce_mbx)); 440 fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload; 441 fwcmd->params.req.id = mq->mq_id; 442 (void) oce_destroy_q(dev, &mbx, 443 sizeof (struct mbx_destroy_common_mq), 444 QTYPE_MQ); 445 oce_cq_del(dev, mq->cq); 446 mq->cq = NULL; 447 mutex_destroy(&mq->lock); 448 kmem_free(mq, sizeof (struct oce_mq)); 449 } /* oce_mq_del */ 450 451 /* 452 * function to create a WQ for NIC Tx 453 * 454 * dev - software handle to the device 455 * wqcfg - configuration structure providing WQ config parameters 456 * 457 * return pointer to the WQ created. NULL on failure 458 */ 459 static struct oce_wq * 460 oce_wq_init(struct oce_dev *dev, uint32_t q_len, int wq_type) 461 { 462 struct oce_wq *wq; 463 char str[MAX_POOL_NAME]; 464 int ret; 465 466 ASSERT(dev != NULL); 467 /* q_len must be min 256 and max 2k */ 468 if (q_len < 256 || q_len > 2048) { 469 oce_log(dev, CE_WARN, MOD_CONFIG, 470 "Invalid q length. Must be " 471 "[256, 2000]: 0x%x", q_len); 472 return (NULL); 473 } 474 475 /* allocate wq */ 476 wq = kmem_zalloc(sizeof (struct oce_wq), KM_NOSLEEP); 477 if (wq == NULL) { 478 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 479 "WQ allocation failed"); 480 return (NULL); 481 } 482 483 /* Set the wq config */ 484 wq->cfg.q_len = q_len; 485 wq->cfg.wq_type = (uint8_t)wq_type; 486 wq->cfg.eqd = OCE_DEFAULT_WQ_EQD; 487 wq->cfg.nbufs = 2 * wq->cfg.q_len; 488 wq->cfg.nhdl = 2 * wq->cfg.q_len; 489 490 /* assign parent */ 491 wq->parent = (void *)dev; 492 493 /* Create the WQ Buffer pool */ 494 ret = oce_wqb_cache_create(wq, dev->tx_bcopy_limit); 495 if (ret != DDI_SUCCESS) { 496 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 497 "WQ Buffer Pool create failed "); 498 goto wqb_fail; 499 } 500 501 /* Create a pool of memory handles */ 502 ret = oce_wqm_cache_create(wq); 503 if (ret != DDI_SUCCESS) { 504 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 505 "WQ MAP Handles Pool create failed "); 506 goto wqm_fail; 507 } 508 509 (void) snprintf(str, MAX_POOL_NAME, "%s%d", "oce_wqed_", dev->dev_id); 510 wq->wqed_cache = kmem_cache_create(str, sizeof (oce_wqe_desc_t), 511 0, oce_wqe_desc_ctor, 512 oce_wqe_desc_dtor, NULL, NULL, NULL, 0); 513 if (wq->wqed_cache == NULL) { 514 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 515 "WQ Packet Desc Pool create failed "); 516 goto wqed_fail; 517 } 518 519 /* create the ring buffer */ 520 wq->ring = create_ring_buffer(dev, q_len, 521 NIC_WQE_SIZE, DDI_DMA_CONSISTENT); 522 if (wq->ring == NULL) { 523 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 524 "Failed to create WQ ring "); 525 goto wq_ringfail; 526 } 527 528 /* Initialize WQ lock */ 529 mutex_init(&wq->tx_lock, NULL, MUTEX_DRIVER, 530 DDI_INTR_PRI(dev->intr_pri)); 531 /* Initialize WQ lock */ 532 mutex_init(&wq->txc_lock, NULL, MUTEX_DRIVER, 533 DDI_INTR_PRI(dev->intr_pri)); 534 atomic_inc_32(&dev->nwqs); 535 536 OCE_LIST_CREATE(&wq->wqe_desc_list, DDI_INTR_PRI(dev->intr_pri)); 537 return (wq); 538 539 wqcq_fail: 540 destroy_ring_buffer(dev, wq->ring); 541 wq_ringfail: 542 kmem_cache_destroy(wq->wqed_cache); 543 wqed_fail: 544 oce_wqm_cache_destroy(wq); 545 wqm_fail: 546 oce_wqb_cache_destroy(wq); 547 wqb_fail: 548 kmem_free(wq, sizeof (struct oce_wq)); 549 return (NULL); 550 } /* oce_wq_create */ 551 552 /* 553 * function to delete a WQ 554 * 555 * dev - software handle to the device 556 * wq - WQ to delete 557 * 558 * return 0 => success, failure otherwise 559 */ 560 static void 561 oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq) 562 { 563 /* destroy cq */ 564 oce_wqb_cache_destroy(wq); 565 oce_wqm_cache_destroy(wq); 566 kmem_cache_destroy(wq->wqed_cache); 567 568 /* Free the packet descriptor list */ 569 OCE_LIST_DESTROY(&wq->wqe_desc_list); 570 destroy_ring_buffer(dev, wq->ring); 571 wq->ring = NULL; 572 /* Destroy the Mutex */ 573 mutex_destroy(&wq->tx_lock); 574 mutex_destroy(&wq->txc_lock); 575 kmem_free(wq, sizeof (struct oce_wq)); 576 atomic_dec_32(&dev->nwqs); 577 } /* oce_wq_del */ 578 579 580 static int 581 oce_wq_create(struct oce_wq *wq, struct oce_eq *eq) 582 { 583 584 struct oce_mbx mbx; 585 struct mbx_create_nic_wq *fwcmd; 586 struct oce_dev *dev = wq->parent; 587 struct oce_cq *cq; 588 int ret; 589 590 /* create the CQ */ 591 cq = oce_cq_create(dev, eq, CQ_LEN_1024, 592 sizeof (struct oce_nic_tx_cqe), 593 B_FALSE, B_TRUE, B_FALSE, 3); 594 if (cq == NULL) { 595 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 596 "WCCQ create failed "); 597 return (DDI_FAILURE); 598 } 599 /* now fill the command */ 600 bzero(&mbx, sizeof (struct oce_mbx)); 601 fwcmd = (struct mbx_create_nic_wq *)&mbx.payload; 602 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 603 MBX_SUBSYSTEM_NIC, 604 OPCODE_CREATE_NIC_WQ, MBX_TIMEOUT_SEC, 605 sizeof (struct mbx_create_nic_wq)); 606 607 fwcmd->params.req.nic_wq_type = (uint8_t)wq->cfg.wq_type; 608 fwcmd->params.req.num_pages = wq->ring->dbuf->num_pages; 609 oce_log(dev, CE_NOTE, MOD_CONFIG, "NUM_PAGES = 0x%d size = %lu", 610 (uint32_t)wq->ring->dbuf->num_pages, 611 wq->ring->dbuf->size); 612 613 /* workaround: fill 0x01 for ulp_mask in rsvd0 */ 614 fwcmd->params.req.rsvd0 = 0x01; 615 fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1; 616 fwcmd->params.req.valid = 1; 617 fwcmd->params.req.pd_id = 0; 618 fwcmd->params.req.pci_function_id = dev->fn; 619 fwcmd->params.req.cq_id = cq->cq_id; 620 621 oce_page_list(wq->ring->dbuf, fwcmd->params.req.pages, 622 wq->ring->dbuf->num_pages); 623 624 /* fill rest of mbx */ 625 mbx.u0.s.embedded = 1; 626 mbx.payload_length = sizeof (struct mbx_create_nic_wq); 627 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 628 629 /* now post the command */ 630 ret = oce_mbox_post(dev, &mbx, NULL); 631 if (ret != DDI_SUCCESS) { 632 oce_log(dev, CE_WARN, MOD_CONFIG, 633 "WQ create failed: %d", ret); 634 oce_cq_del(dev, cq); 635 return (ret); 636 637 } 638 639 /* interpret the response */ 640 wq->wq_id = LE_16(fwcmd->params.rsp.wq_id); 641 wq->qstate = QCREATED; 642 wq->cq = cq; 643 /* set the WQCQ handlers */ 644 wq->cq->cq_handler = oce_drain_wq_cq; 645 wq->cq->cb_arg = (void *)wq; 646 /* All are free to start with */ 647 wq->wq_free = wq->cfg.q_len; 648 /* reset indicies */ 649 wq->ring->cidx = 0; 650 wq->ring->pidx = 0; 651 return (0); 652 } 653 654 /* 655 * function to delete a WQ 656 * 657 * dev - software handle to the device 658 * wq - WQ to delete 659 * 660 * return none 661 */ 662 static void 663 oce_wq_del(struct oce_dev *dev, struct oce_wq *wq) 664 { 665 struct oce_mbx mbx; 666 struct mbx_delete_nic_wq *fwcmd; 667 668 669 ASSERT(dev != NULL); 670 ASSERT(wq != NULL); 671 if (wq->qstate == QCREATED) { 672 bzero(&mbx, sizeof (struct oce_mbx)); 673 /* now fill the command */ 674 fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload; 675 fwcmd->params.req.wq_id = wq->wq_id; 676 (void) oce_destroy_q(dev, &mbx, 677 sizeof (struct mbx_delete_nic_wq), 678 QTYPE_WQ); 679 wq->qstate = QDELETED; 680 oce_cq_del(dev, wq->cq); 681 wq->cq = NULL; 682 } 683 } /* oce_wq_del */ 684 685 /* 686 * function to allocate RQ resources 687 * 688 * dev - software handle to the device 689 * rqcfg - configuration structure providing RQ config parameters 690 * 691 * return pointer to the RQ created. NULL on failure 692 */ 693 /* ARGSUSED */ 694 static struct oce_rq * 695 oce_rq_init(struct oce_dev *dev, uint32_t q_len, 696 uint32_t frag_size, uint32_t mtu, 697 boolean_t rss) 698 { 699 700 struct oce_rq *rq; 701 int ret; 702 703 /* validate q creation parameters */ 704 if (!OCE_LOG2(frag_size)) 705 return (NULL); 706 if ((q_len == 0) || (q_len > 1024)) 707 return (NULL); 708 709 /* allocate the rq */ 710 rq = kmem_zalloc(sizeof (struct oce_rq), KM_NOSLEEP); 711 if (rq == NULL) { 712 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 713 "RQ allocation failed"); 714 return (NULL); 715 } 716 717 rq->cfg.q_len = q_len; 718 rq->cfg.frag_size = frag_size; 719 rq->cfg.mtu = mtu; 720 rq->cfg.eqd = 0; 721 rq->cfg.nbufs = 8 * 1024; 722 723 /* assign parent */ 724 rq->parent = (void *)dev; 725 726 /* create the cache */ 727 ret = oce_rqb_cache_create(rq, OCE_RQ_BUF_SIZE + 728 OCE_RQE_BUF_HEADROOM); 729 if (ret != DDI_SUCCESS) { 730 goto rqb_fail; 731 } 732 733 /* create the ring buffer */ 734 rq->ring = create_ring_buffer(dev, q_len, 735 sizeof (struct oce_nic_rqe), DDI_DMA_CONSISTENT); 736 if (rq->ring == NULL) { 737 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 738 "RQ ring create failed "); 739 goto rq_ringfail; 740 } 741 742 /* allocate mbx */ 743 rq->shadow_ring = kmem_zalloc(sizeof (struct rq_shadow_entry) * 744 q_len, KM_SLEEP); 745 746 /* Initialize the RQ lock */ 747 mutex_init(&rq->rx_lock, NULL, MUTEX_DRIVER, 748 DDI_INTR_PRI(dev->intr_pri)); 749 /* Initialize the recharge lock */ 750 mutex_init(&rq->rc_lock, NULL, MUTEX_DRIVER, 751 DDI_INTR_PRI(dev->intr_pri)); 752 atomic_inc_32(&dev->nrqs); 753 return (rq); 754 755 rqcq_fail: 756 kmem_free(rq->shadow_ring, 757 sizeof (struct rq_shadow_entry) * q_len); 758 destroy_ring_buffer(dev, rq->ring); 759 rq_ringfail: 760 oce_rqb_cache_destroy(rq); 761 rqb_fail: 762 kmem_free(rq, sizeof (struct oce_rq)); 763 return (NULL); 764 } /* oce_rq_create */ 765 766 /* 767 * function to delete an RQ 768 * 769 * dev - software handle to the device 770 * rq - RQ to delete 771 * 772 * return none 773 */ 774 static void 775 oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq) 776 { 777 /* Destroy buffer cache */ 778 oce_rqb_cache_destroy(rq); 779 destroy_ring_buffer(dev, rq->ring); 780 rq->ring = NULL; 781 kmem_free(rq->shadow_ring, 782 sizeof (struct rq_shadow_entry) * rq->cfg.q_len); 783 rq->shadow_ring = NULL; 784 mutex_destroy(&rq->rx_lock); 785 mutex_destroy(&rq->rc_lock); 786 kmem_free(rq, sizeof (struct oce_rq)); 787 atomic_dec_32(&dev->nrqs); 788 } /* oce_rq_del */ 789 790 791 static int 792 oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq) 793 { 794 struct oce_mbx mbx; 795 struct mbx_create_nic_rq *fwcmd; 796 struct oce_dev *dev = rq->parent; 797 struct oce_cq *cq; 798 int ret; 799 800 cq = oce_cq_create(dev, eq, CQ_LEN_1024, sizeof (struct oce_nic_rx_cqe), 801 B_FALSE, B_TRUE, B_FALSE, 3); 802 803 if (cq == NULL) { 804 return (DDI_FAILURE); 805 } 806 807 /* now fill the command */ 808 bzero(&mbx, sizeof (struct oce_mbx)); 809 fwcmd = (struct mbx_create_nic_rq *)&mbx.payload; 810 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 811 MBX_SUBSYSTEM_NIC, 812 OPCODE_CREATE_NIC_RQ, MBX_TIMEOUT_SEC, 813 sizeof (struct mbx_create_nic_rq)); 814 815 fwcmd->params.req.num_pages = rq->ring->dbuf->num_pages; 816 fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size); 817 fwcmd->params.req.cq_id = cq->cq_id; 818 oce_page_list(rq->ring->dbuf, fwcmd->params.req.pages, 819 rq->ring->dbuf->num_pages); 820 821 fwcmd->params.req.if_id = if_id; 822 fwcmd->params.req.max_frame_size = (uint16_t)rq->cfg.mtu; 823 fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue; 824 825 /* fill rest of mbx */ 826 mbx.u0.s.embedded = 1; 827 mbx.payload_length = sizeof (struct mbx_create_nic_rq); 828 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 829 830 /* now post the command */ 831 ret = oce_mbox_post(dev, &mbx, NULL); 832 if (ret != 0) { 833 oce_log(dev, CE_WARN, MOD_CONFIG, 834 "RQ create failed: %d", ret); 835 oce_cq_del(dev, cq); 836 return (ret); 837 } 838 839 /* interpret the response */ 840 rq->rq_id = LE_16(fwcmd->params.rsp.u0.s.rq_id); 841 /* rq->rss_cpuid = fwcmd->params.rsp.u0.bits.rss_cpuid; */ 842 rq->cfg.if_id = if_id; 843 rq->qstate = QCREATED; 844 rq->cq = cq; 845 846 /* set the Completion Handler */ 847 rq->cq->cq_handler = oce_drain_rq_cq; 848 rq->cq->cb_arg = (void *)rq; 849 /* reset the indicies */ 850 rq->ring->cidx = 0; 851 rq->ring->pidx = 0; 852 rq->buf_avail = 0; 853 return (0); 854 855 } 856 857 /* 858 * function to delete an RQ 859 * 860 * dev - software handle to the device 861 * rq - RQ to delete 862 * 863 * return none 864 */ 865 static void 866 oce_rq_del(struct oce_dev *dev, struct oce_rq *rq) 867 { 868 struct oce_mbx mbx; 869 struct mbx_delete_nic_rq *fwcmd; 870 871 ASSERT(dev != NULL); 872 ASSERT(rq != NULL); 873 874 bzero(&mbx, sizeof (struct oce_mbx)); 875 876 /* delete the Queue */ 877 if (rq->qstate == QCREATED) { 878 fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; 879 fwcmd->params.req.rq_id = rq->rq_id; 880 (void) oce_destroy_q(dev, &mbx, 881 sizeof (struct mbx_delete_nic_rq), QTYPE_RQ); 882 rq->qstate = QDELETED; 883 oce_clean_rq(rq); 884 /* Delete the associated CQ */ 885 oce_cq_del(dev, rq->cq); 886 rq->cq = NULL; 887 /* free up the posted buffers */ 888 oce_rq_discharge(dev->rq[0]); 889 } 890 } /* oce_rq_del */ 891 892 /* 893 * function to arm an EQ so that it can generate events 894 * 895 * dev - software handle to the device 896 * qid - id of the EQ returned by the fw at the time of creation 897 * npopped - number of EQEs to arm with 898 * rearm - rearm bit 899 * clearint - bit to clear the interrupt condition because of which 900 * EQEs are generated 901 * 902 * return none 903 */ 904 void 905 oce_arm_eq(struct oce_dev *dev, int16_t qid, int npopped, 906 boolean_t rearm, boolean_t clearint) 907 { 908 eq_db_t eq_db = {0}; 909 910 eq_db.bits.rearm = rearm; 911 eq_db.bits.event = B_TRUE; 912 eq_db.bits.num_popped = npopped; 913 eq_db.bits.clrint = clearint; 914 eq_db.bits.qid = qid; 915 OCE_DB_WRITE32(dev, PD_EQ_DB, eq_db.dw0); 916 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) { 917 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); 918 } 919 } 920 921 /* 922 * function to arm a CQ with CQEs 923 * 924 * dev - software handle to the device 925 * qid - the id of the CQ returned by the fw at the time of creation 926 * npopped - number of CQEs to arm with 927 * rearm - rearm bit enable/disable 928 * 929 * return none 930 */ 931 void 932 oce_arm_cq(struct oce_dev *dev, int16_t qid, int npopped, 933 boolean_t rearm) 934 { 935 cq_db_t cq_db = {0}; 936 cq_db.bits.rearm = rearm; 937 cq_db.bits.num_popped = npopped; 938 cq_db.bits.event = 0; 939 cq_db.bits.qid = qid; 940 OCE_DB_WRITE32(dev, PD_CQ_DB, cq_db.dw0); 941 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) { 942 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); 943 } 944 } 945 946 947 /* 948 * function to delete a EQ, CQ, MQ, WQ or RQ 949 * 950 * dev - sofware handle to the device 951 * mbx - mbox command to send to the fw to delete the queue 952 * mbx contains the queue information to delete 953 * req_size - the size of the mbx payload dependent on the qtype 954 * qtype - the type of queue i.e. EQ, CQ, MQ, WQ or RQ 955 * 956 * return DDI_SUCCESS => success, failure otherwise 957 */ 958 int 959 oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx, size_t req_size, 960 enum qtype qtype) 961 { 962 struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload; 963 int opcode; 964 int subsys; 965 int ret; 966 967 switch (qtype) { 968 case QTYPE_EQ: { 969 opcode = OPCODE_DESTROY_COMMON_EQ; 970 subsys = MBX_SUBSYSTEM_COMMON; 971 break; 972 } 973 case QTYPE_CQ: { 974 opcode = OPCODE_DESTROY_COMMON_CQ; 975 subsys = MBX_SUBSYSTEM_COMMON; 976 break; 977 } 978 case QTYPE_MQ: { 979 opcode = OPCODE_DESTROY_COMMON_MQ; 980 subsys = MBX_SUBSYSTEM_COMMON; 981 break; 982 } 983 case QTYPE_WQ: { 984 opcode = OPCODE_DELETE_NIC_WQ; 985 subsys = MBX_SUBSYSTEM_NIC; 986 break; 987 } 988 case QTYPE_RQ: { 989 opcode = OPCODE_DELETE_NIC_RQ; 990 subsys = MBX_SUBSYSTEM_NIC; 991 break; 992 } 993 default: { 994 ASSERT(0); 995 break; 996 } 997 } 998 999 mbx_common_req_hdr_init(hdr, 0, 0, subsys, 1000 opcode, MBX_TIMEOUT_SEC, req_size); 1001 1002 /* fill rest of mbx */ 1003 mbx->u0.s.embedded = 1; 1004 mbx->payload_length = (uint32_t)req_size; 1005 DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); 1006 1007 /* send command */ 1008 ret = oce_mbox_post(dev, mbx, NULL); 1009 1010 if (ret != 0) { 1011 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 1012 "Failed to del q "); 1013 } 1014 return (ret); 1015 } 1016 1017 /* 1018 * function to set the delay parameter in the EQ for interrupt coalescing 1019 * 1020 * dev - software handle to the device 1021 * eq_arr - array of EQ ids to delete 1022 * eq_cnt - number of elements in eq_arr 1023 * eq_delay - delay parameter 1024 * 1025 * return DDI_SUCCESS => success, failure otherwise 1026 */ 1027 int 1028 oce_set_eq_delay(struct oce_dev *dev, uint32_t *eq_arr, 1029 uint32_t eq_cnt, uint32_t eq_delay) 1030 { 1031 struct oce_mbx mbx; 1032 struct mbx_modify_common_eq_delay *fwcmd; 1033 int ret; 1034 int neq; 1035 1036 bzero(&mbx, sizeof (struct oce_mbx)); 1037 fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload; 1038 1039 /* fill the command */ 1040 fwcmd->params.req.num_eq = eq_cnt; 1041 for (neq = 0; neq < eq_cnt; neq++) { 1042 fwcmd->params.req.delay[neq].eq_id = eq_arr[neq]; 1043 fwcmd->params.req.delay[neq].phase = 0; 1044 fwcmd->params.req.delay[neq].dm = eq_delay; 1045 1046 } 1047 1048 /* initialize the ioctl header */ 1049 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 1050 MBX_SUBSYSTEM_COMMON, 1051 OPCODE_MODIFY_COMMON_EQ_DELAY, 1052 MBX_TIMEOUT_SEC, 1053 sizeof (struct mbx_modify_common_eq_delay)); 1054 1055 /* fill rest of mbx */ 1056 mbx.u0.s.embedded = 1; 1057 mbx.payload_length = sizeof (struct mbx_modify_common_eq_delay); 1058 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 1059 1060 /* post the command */ 1061 ret = oce_mbox_post(dev, &mbx, NULL); 1062 if (ret != 0) { 1063 oce_log(dev, CE_WARN, MOD_CONFIG, 1064 "Failed to set EQ delay %d", ret); 1065 } 1066 1067 return (ret); 1068 } /* oce_set_eq_delay */ 1069 1070 /* 1071 * function to cleanup the eqs used during stop 1072 * 1073 * eq - pointer to event queue structure 1074 * 1075 * return none 1076 */ 1077 void 1078 oce_drain_eq(struct oce_eq *eq) 1079 { 1080 struct oce_eqe *eqe; 1081 uint16_t num_eqe = 0; 1082 struct oce_dev *dev; 1083 1084 dev = eq->parent; 1085 /* get the first item in eq to process */ 1086 eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe); 1087 1088 while (eqe->u0.dw0) { 1089 eqe->u0.dw0 = LE_32(eqe->u0.dw0); 1090 1091 /* clear valid bit */ 1092 eqe->u0.dw0 = 0; 1093 1094 /* process next eqe */ 1095 RING_GET(eq->ring, 1); 1096 1097 eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe); 1098 num_eqe++; 1099 } /* for all EQEs */ 1100 if (num_eqe) { 1101 oce_arm_eq(dev, eq->eq_id, num_eqe, B_FALSE, B_TRUE); 1102 } 1103 } /* oce_drain_eq */ 1104 1105 1106 int 1107 oce_init_txrx(struct oce_dev *dev) 1108 { 1109 dev->wq[0] = oce_wq_init(dev, dev->tx_ring_size, NIC_WQ_TYPE_STANDARD); 1110 1111 if (dev->wq[0] == NULL) { 1112 goto queue_fail; 1113 } 1114 1115 dev->rq[0] = oce_rq_init(dev, dev->rx_ring_size, OCE_RQ_BUF_SIZE, 1116 OCE_RQ_MAX_FRAME_SZ, B_FALSE); 1117 if (dev->rq[0] == NULL) { 1118 goto queue_fail; 1119 } 1120 return (DDI_SUCCESS); 1121 queue_fail: 1122 oce_fini_txrx(dev); 1123 return (DDI_FAILURE); 1124 } 1125 void 1126 oce_fini_txrx(struct oce_dev *dev) 1127 { 1128 if (dev->wq[0] != NULL) { 1129 oce_wq_fini(dev, dev->wq[0]); 1130 dev->wq[0] = NULL; 1131 } 1132 if (dev->rq[0] != NULL) { 1133 oce_rq_fini(dev, dev->rq[0]); 1134 dev->rq[0] = NULL; 1135 } 1136 return; 1137 1138 } 1139 1140 int 1141 oce_create_queues(struct oce_dev *dev) 1142 { 1143 1144 int i; 1145 struct oce_eq *eq; 1146 struct oce_mq *mq; 1147 1148 for (i = 0; i < dev->num_vectors; i++) { 1149 eq = oce_eq_create(dev, EQ_LEN_1024, EQE_SIZE_4, 0); 1150 if (eq == NULL) { 1151 goto rings_fail; 1152 } 1153 dev->eq[i] = eq; 1154 } 1155 if (oce_wq_create(dev->wq[0], dev->eq[0]) != 0) 1156 goto rings_fail; 1157 if (oce_rq_create(dev->rq[0], dev->if_id, 1158 dev->neqs > 1 ? dev->eq[1] : dev->eq[0]) != 0) 1159 goto rings_fail; 1160 mq = oce_mq_create(dev, dev->eq[0], 64); 1161 if (mq == NULL) 1162 goto rings_fail; 1163 dev->mq = mq; 1164 return (DDI_SUCCESS); 1165 rings_fail: 1166 oce_delete_queues(dev); 1167 return (DDI_FAILURE); 1168 1169 } 1170 1171 void 1172 oce_delete_queues(struct oce_dev *dev) 1173 { 1174 int i; 1175 if (dev->mq != NULL) { 1176 oce_mq_del(dev, dev->mq); 1177 dev->mq = NULL; 1178 } 1179 1180 for (i = 0; i < dev->nrqs; i++) { 1181 oce_rq_del(dev, dev->rq[i]); 1182 } 1183 for (i = 0; i < dev->nwqs; i++) { 1184 oce_wq_del(dev, dev->wq[i]); 1185 } 1186 /* create as many eqs as the number of vectors */ 1187 for (i = 0; i < dev->num_vectors; i++) { 1188 oce_eq_del(dev, dev->eq[i]); 1189 dev->eq[i] = NULL; 1190 } 1191 } 1192