1/* 2 * linux/drivers/net/ehea/ehea_qmr.c 3 * 4 * eHEA ethernet device driver for IBM eServer System p 5 * 6 * (C) Copyright IBM Corp. 2006 7 * 8 * Authors: 9 * Christoph Raisch <raisch@de.ibm.com> 10 * Jan-Bernd Themann <themann@de.ibm.com> 11 * Thomas Klein <tklein@de.ibm.com> 12 * 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2, or (at your option) 17 * any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 */ 28 29#include <linux/mm.h> 30#include "ehea.h" 31#include "ehea_phyp.h" 32#include "ehea_qmr.h" 33 34static void *hw_qpageit_get_inc(struct hw_queue *queue) 35{ 36 void *retvalue = hw_qeit_get(queue); 37 38 queue->current_q_offset += queue->pagesize; 39 if (queue->current_q_offset > queue->queue_length) { 40 queue->current_q_offset -= queue->pagesize; 41 retvalue = NULL; 42 } else if (((u64) retvalue) & (EHEA_PAGESIZE-1)) { 43 ehea_error("not on pageboundary"); 44 retvalue = NULL; 45 } 46 return retvalue; 47} 48 49static int hw_queue_ctor(struct hw_queue *queue, const u32 nr_of_pages, 50 const u32 pagesize, const u32 qe_size) 51{ 52 int pages_per_kpage = PAGE_SIZE / pagesize; 53 int i, k; 54 55 if ((pagesize > PAGE_SIZE) || (!pages_per_kpage)) { 56 ehea_error("pagesize conflict! kernel pagesize=%d, " 57 "ehea pagesize=%d", (int)PAGE_SIZE, (int)pagesize); 58 return -EINVAL; 59 } 60 61 queue->queue_length = nr_of_pages * pagesize; 62 queue->queue_pages = kmalloc(nr_of_pages * sizeof(void*), GFP_KERNEL); 63 if (!queue->queue_pages) { 64 ehea_error("no mem for queue_pages"); 65 return -ENOMEM; 66 } 67 68 /* 69 * allocate pages for queue: 70 * outer loop allocates whole kernel pages (page aligned) and 71 * inner loop divides a kernel page into smaller hea queue pages 72 */ 73 i = 0; 74 while (i < nr_of_pages) { 75 u8 *kpage = (u8*)get_zeroed_page(GFP_KERNEL); 76 if (!kpage) 77 goto out_nomem; 78 for (k = 0; k < pages_per_kpage && i < nr_of_pages; k++) { 79 (queue->queue_pages)[i] = (struct ehea_page*)kpage; 80 kpage += pagesize; 81 i++; 82 } 83 } 84 85 queue->current_q_offset = 0; 86 queue->qe_size = qe_size; 87 queue->pagesize = pagesize; 88 queue->toggle_state = 1; 89 90 return 0; 91out_nomem: 92 for (i = 0; i < nr_of_pages; i += pages_per_kpage) { 93 if (!(queue->queue_pages)[i]) 94 break; 95 free_page((unsigned long)(queue->queue_pages)[i]); 96 } 97 return -ENOMEM; 98} 99 100static void hw_queue_dtor(struct hw_queue *queue) 101{ 102 int pages_per_kpage = PAGE_SIZE / queue->pagesize; 103 int i, nr_pages; 104 105 if (!queue || !queue->queue_pages) 106 return; 107 108 nr_pages = queue->queue_length / queue->pagesize; 109 110 for (i = 0; i < nr_pages; i += pages_per_kpage) 111 free_page((unsigned long)(queue->queue_pages)[i]); 112 113 kfree(queue->queue_pages); 114} 115 116struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, 117 int nr_of_cqe, u64 eq_handle, u32 cq_token) 118{ 119 struct ehea_cq *cq; 120 struct h_epa epa; 121 u64 *cq_handle_ref, hret, rpage; 122 u32 act_nr_of_entries, act_pages, counter; 123 int ret; 124 void *vpage; 125 126 cq = kzalloc(sizeof(*cq), GFP_KERNEL); 127 if (!cq) { 128 ehea_error("no mem for cq"); 129 goto out_nomem; 130 } 131 132 cq->attr.max_nr_of_cqes = nr_of_cqe; 133 cq->attr.cq_token = cq_token; 134 cq->attr.eq_handle = eq_handle; 135 136 cq->adapter = adapter; 137 138 cq_handle_ref = &cq->fw_handle; 139 act_nr_of_entries = 0; 140 act_pages = 0; 141 142 hret = ehea_h_alloc_resource_cq(adapter->handle, &cq->attr, 143 &cq->fw_handle, &cq->epas); 144 if (hret != H_SUCCESS) { 145 ehea_error("alloc_resource_cq failed"); 146 goto out_freemem; 147 } 148 149 ret = hw_queue_ctor(&cq->hw_queue, cq->attr.nr_pages, 150 EHEA_PAGESIZE, sizeof(struct ehea_cqe)); 151 if (ret) 152 goto out_freeres; 153 154 for (counter = 0; counter < cq->attr.nr_pages; counter++) { 155 vpage = hw_qpageit_get_inc(&cq->hw_queue); 156 if (!vpage) { 157 ehea_error("hw_qpageit_get_inc failed"); 158 goto out_kill_hwq; 159 } 160 161 rpage = virt_to_abs(vpage); 162 hret = ehea_h_register_rpage(adapter->handle, 163 0, EHEA_CQ_REGISTER_ORIG, 164 cq->fw_handle, rpage, 1); 165 if (hret < H_SUCCESS) { 166 ehea_error("register_rpage_cq failed ehea_cq=%p " 167 "hret=%lx counter=%i act_pages=%i", 168 cq, hret, counter, cq->attr.nr_pages); 169 goto out_kill_hwq; 170 } 171 172 if (counter == (cq->attr.nr_pages - 1)) { 173 vpage = hw_qpageit_get_inc(&cq->hw_queue); 174 175 if ((hret != H_SUCCESS) || (vpage)) { 176 ehea_error("registration of pages not " 177 "complete hret=%lx\n", hret); 178 goto out_kill_hwq; 179 } 180 } else { 181 if ((hret != H_PAGE_REGISTERED) || (!vpage)) { 182 ehea_error("CQ: registration of page failed " 183 "hret=%lx\n", hret); 184 goto out_kill_hwq; 185 } 186 } 187 } 188 189 hw_qeit_reset(&cq->hw_queue); 190 epa = cq->epas.kernel; 191 ehea_reset_cq_ep(cq); 192 ehea_reset_cq_n1(cq); 193 194 return cq; 195 196out_kill_hwq: 197 hw_queue_dtor(&cq->hw_queue); 198 199out_freeres: 200 ehea_h_free_resource(adapter->handle, cq->fw_handle, FORCE_FREE); 201 202out_freemem: 203 kfree(cq); 204 205out_nomem: 206 return NULL; 207} 208 209u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force) 210{ 211 u64 hret; 212 u64 adapter_handle = cq->adapter->handle; 213 214 /* deregister all previous registered pages */ 215 hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force); 216 if (hret != H_SUCCESS) 217 return hret; 218 219 hw_queue_dtor(&cq->hw_queue); 220 kfree(cq); 221 222 return hret; 223} 224 225int ehea_destroy_cq(struct ehea_cq *cq) 226{ 227 u64 hret; 228 if (!cq) 229 return 0; 230 231 if ((hret = ehea_destroy_cq_res(cq, NORMAL_FREE)) == H_R_STATE) { 232 ehea_error_data(cq->adapter, cq->fw_handle); 233 hret = ehea_destroy_cq_res(cq, FORCE_FREE); 234 } 235 236 if (hret != H_SUCCESS) { 237 ehea_error("destroy CQ failed"); 238 return -EIO; 239 } 240 241 return 0; 242} 243 244struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter, 245 const enum ehea_eq_type type, 246 const u32 max_nr_of_eqes, const u8 eqe_gen) 247{ 248 int ret, i; 249 u64 hret, rpage; 250 void *vpage; 251 struct ehea_eq *eq; 252 253 eq = kzalloc(sizeof(*eq), GFP_KERNEL); 254 if (!eq) { 255 ehea_error("no mem for eq"); 256 return NULL; 257 } 258 259 eq->adapter = adapter; 260 eq->attr.type = type; 261 eq->attr.max_nr_of_eqes = max_nr_of_eqes; 262 eq->attr.eqe_gen = eqe_gen; 263 spin_lock_init(&eq->spinlock); 264 265 hret = ehea_h_alloc_resource_eq(adapter->handle, 266 &eq->attr, &eq->fw_handle); 267 if (hret != H_SUCCESS) { 268 ehea_error("alloc_resource_eq failed"); 269 goto out_freemem; 270 } 271 272 ret = hw_queue_ctor(&eq->hw_queue, eq->attr.nr_pages, 273 EHEA_PAGESIZE, sizeof(struct ehea_eqe)); 274 if (ret) { 275 ehea_error("can't allocate eq pages"); 276 goto out_freeres; 277 } 278 279 for (i = 0; i < eq->attr.nr_pages; i++) { 280 vpage = hw_qpageit_get_inc(&eq->hw_queue); 281 if (!vpage) { 282 ehea_error("hw_qpageit_get_inc failed"); 283 hret = H_RESOURCE; 284 goto out_kill_hwq; 285 } 286 287 rpage = virt_to_abs(vpage); 288 289 hret = ehea_h_register_rpage(adapter->handle, 0, 290 EHEA_EQ_REGISTER_ORIG, 291 eq->fw_handle, rpage, 1); 292 293 if (i == (eq->attr.nr_pages - 1)) { 294 /* last page */ 295 vpage = hw_qpageit_get_inc(&eq->hw_queue); 296 if ((hret != H_SUCCESS) || (vpage)) { 297 goto out_kill_hwq; 298 } 299 } else { 300 if ((hret != H_PAGE_REGISTERED) || (!vpage)) { 301 goto out_kill_hwq; 302 } 303 } 304 } 305 306 hw_qeit_reset(&eq->hw_queue); 307 return eq; 308 309out_kill_hwq: 310 hw_queue_dtor(&eq->hw_queue); 311 312out_freeres: 313 ehea_h_free_resource(adapter->handle, eq->fw_handle, FORCE_FREE); 314 315out_freemem: 316 kfree(eq); 317 return NULL; 318} 319 320struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq) 321{ 322 struct ehea_eqe *eqe; 323 unsigned long flags; 324 325 spin_lock_irqsave(&eq->spinlock, flags); 326 eqe = (struct ehea_eqe*)hw_eqit_eq_get_inc_valid(&eq->hw_queue); 327 spin_unlock_irqrestore(&eq->spinlock, flags); 328 329 return eqe; 330} 331 332u64 ehea_destroy_eq_res(struct ehea_eq *eq, u64 force) 333{ 334 u64 hret; 335 unsigned long flags; 336 337 spin_lock_irqsave(&eq->spinlock, flags); 338 339 hret = ehea_h_free_resource(eq->adapter->handle, eq->fw_handle, force); 340 spin_unlock_irqrestore(&eq->spinlock, flags); 341 342 if (hret != H_SUCCESS) 343 return hret; 344 345 hw_queue_dtor(&eq->hw_queue); 346 kfree(eq); 347 348 return hret; 349} 350 351int ehea_destroy_eq(struct ehea_eq *eq) 352{ 353 u64 hret; 354 if (!eq) 355 return 0; 356 357 if ((hret = ehea_destroy_eq_res(eq, NORMAL_FREE)) == H_R_STATE) { 358 ehea_error_data(eq->adapter, eq->fw_handle); 359 hret = ehea_destroy_eq_res(eq, FORCE_FREE); 360 } 361 362 if (hret != H_SUCCESS) { 363 ehea_error("destroy EQ failed"); 364 return -EIO; 365 } 366 367 return 0; 368} 369 370/** 371 * allocates memory for a queue and registers pages in phyp 372 */ 373int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue, 374 int nr_pages, int wqe_size, int act_nr_sges, 375 struct ehea_adapter *adapter, int h_call_q_selector) 376{ 377 u64 hret, rpage; 378 int ret, cnt; 379 void *vpage; 380 381 ret = hw_queue_ctor(hw_queue, nr_pages, EHEA_PAGESIZE, wqe_size); 382 if (ret) 383 return ret; 384 385 for (cnt = 0; cnt < nr_pages; cnt++) { 386 vpage = hw_qpageit_get_inc(hw_queue); 387 if (!vpage) { 388 ehea_error("hw_qpageit_get_inc failed"); 389 goto out_kill_hwq; 390 } 391 rpage = virt_to_abs(vpage); 392 hret = ehea_h_register_rpage(adapter->handle, 393 0, h_call_q_selector, 394 qp->fw_handle, rpage, 1); 395 if (hret < H_SUCCESS) { 396 ehea_error("register_rpage_qp failed"); 397 goto out_kill_hwq; 398 } 399 } 400 hw_qeit_reset(hw_queue); 401 return 0; 402 403out_kill_hwq: 404 hw_queue_dtor(hw_queue); 405 return -EIO; 406} 407 408static inline u32 map_wqe_size(u8 wqe_enc_size) 409{ 410 return 128 << wqe_enc_size; 411} 412 413struct ehea_qp *ehea_create_qp(struct ehea_adapter *adapter, 414 u32 pd, struct ehea_qp_init_attr *init_attr) 415{ 416 int ret; 417 u64 hret; 418 struct ehea_qp *qp; 419 u32 wqe_size_in_bytes_sq, wqe_size_in_bytes_rq1; 420 u32 wqe_size_in_bytes_rq2, wqe_size_in_bytes_rq3; 421 422 423 qp = kzalloc(sizeof(*qp), GFP_KERNEL); 424 if (!qp) { 425 ehea_error("no mem for qp"); 426 return NULL; 427 } 428 429 qp->adapter = adapter; 430 431 hret = ehea_h_alloc_resource_qp(adapter->handle, init_attr, pd, 432 &qp->fw_handle, &qp->epas); 433 if (hret != H_SUCCESS) { 434 ehea_error("ehea_h_alloc_resource_qp failed"); 435 goto out_freemem; 436 } 437 438 wqe_size_in_bytes_sq = map_wqe_size(init_attr->act_wqe_size_enc_sq); 439 wqe_size_in_bytes_rq1 = map_wqe_size(init_attr->act_wqe_size_enc_rq1); 440 wqe_size_in_bytes_rq2 = map_wqe_size(init_attr->act_wqe_size_enc_rq2); 441 wqe_size_in_bytes_rq3 = map_wqe_size(init_attr->act_wqe_size_enc_rq3); 442 443 ret = ehea_qp_alloc_register(qp, &qp->hw_squeue, init_attr->nr_sq_pages, 444 wqe_size_in_bytes_sq, 445 init_attr->act_wqe_size_enc_sq, adapter, 446 0); 447 if (ret) { 448 ehea_error("can't register for sq ret=%x", ret); 449 goto out_freeres; 450 } 451 452 ret = ehea_qp_alloc_register(qp, &qp->hw_rqueue1, 453 init_attr->nr_rq1_pages, 454 wqe_size_in_bytes_rq1, 455 init_attr->act_wqe_size_enc_rq1, 456 adapter, 1); 457 if (ret) { 458 ehea_error("can't register for rq1 ret=%x", ret); 459 goto out_kill_hwsq; 460 } 461 462 if (init_attr->rq_count > 1) { 463 ret = ehea_qp_alloc_register(qp, &qp->hw_rqueue2, 464 init_attr->nr_rq2_pages, 465 wqe_size_in_bytes_rq2, 466 init_attr->act_wqe_size_enc_rq2, 467 adapter, 2); 468 if (ret) { 469 ehea_error("can't register for rq2 ret=%x", ret); 470 goto out_kill_hwr1q; 471 } 472 } 473 474 if (init_attr->rq_count > 2) { 475 ret = ehea_qp_alloc_register(qp, &qp->hw_rqueue3, 476 init_attr->nr_rq3_pages, 477 wqe_size_in_bytes_rq3, 478 init_attr->act_wqe_size_enc_rq3, 479 adapter, 3); 480 if (ret) { 481 ehea_error("can't register for rq3 ret=%x", ret); 482 goto out_kill_hwr2q; 483 } 484 } 485 486 qp->init_attr = *init_attr; 487 488 return qp; 489 490out_kill_hwr2q: 491 hw_queue_dtor(&qp->hw_rqueue2); 492 493out_kill_hwr1q: 494 hw_queue_dtor(&qp->hw_rqueue1); 495 496out_kill_hwsq: 497 hw_queue_dtor(&qp->hw_squeue); 498 499out_freeres: 500 ehea_h_disable_and_get_hea(adapter->handle, qp->fw_handle); 501 ehea_h_free_resource(adapter->handle, qp->fw_handle, FORCE_FREE); 502 503out_freemem: 504 kfree(qp); 505 return NULL; 506} 507 508u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force) 509{ 510 u64 hret; 511 struct ehea_qp_init_attr *qp_attr = &qp->init_attr; 512 513 514 ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); 515 hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force); 516 if (hret != H_SUCCESS) 517 return hret; 518 519 hw_queue_dtor(&qp->hw_squeue); 520 hw_queue_dtor(&qp->hw_rqueue1); 521 522 if (qp_attr->rq_count > 1) 523 hw_queue_dtor(&qp->hw_rqueue2); 524 if (qp_attr->rq_count > 2) 525 hw_queue_dtor(&qp->hw_rqueue3); 526 kfree(qp); 527 528 return hret; 529} 530 531int ehea_destroy_qp(struct ehea_qp *qp) 532{ 533 u64 hret; 534 if (!qp) 535 return 0; 536 537 if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) { 538 ehea_error_data(qp->adapter, qp->fw_handle); 539 hret = ehea_destroy_qp_res(qp, FORCE_FREE); 540 } 541 542 if (hret != H_SUCCESS) { 543 ehea_error("destroy QP failed"); 544 return -EIO; 545 } 546 547 return 0; 548} 549 550int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) 551{ 552 int i, k, ret; 553 u64 hret, pt_abs, start, end, nr_pages; 554 u32 acc_ctrl = EHEA_MR_ACC_CTRL; 555 u64 *pt; 556 557 start = KERNELBASE; 558 end = (u64)high_memory; 559 nr_pages = (end - start) / EHEA_PAGESIZE; 560 561 pt = kzalloc(PAGE_SIZE, GFP_KERNEL); 562 if (!pt) { 563 ehea_error("no mem"); 564 ret = -ENOMEM; 565 goto out; 566 } 567 pt_abs = virt_to_abs(pt); 568 569 hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start, 570 acc_ctrl, adapter->pd, 571 &mr->handle, &mr->lkey); 572 if (hret != H_SUCCESS) { 573 ehea_error("alloc_resource_mr failed"); 574 ret = -EIO; 575 goto out; 576 } 577 578 mr->vaddr = KERNELBASE; 579 k = 0; 580 581 while (nr_pages > 0) { 582 if (nr_pages > 1) { 583 u64 num_pages = min(nr_pages, (u64)512); 584 for (i = 0; i < num_pages; i++) 585 pt[i] = virt_to_abs((void*)(((u64)start) + 586 ((k++) * 587 EHEA_PAGESIZE))); 588 589 hret = ehea_h_register_rpage_mr(adapter->handle, 590 mr->handle, 0, 591 0, (u64)pt_abs, 592 num_pages); 593 nr_pages -= num_pages; 594 } else { 595 u64 abs_adr = virt_to_abs((void*)(((u64)start) + 596 (k * EHEA_PAGESIZE))); 597 598 hret = ehea_h_register_rpage_mr(adapter->handle, 599 mr->handle, 0, 600 0, abs_adr,1); 601 nr_pages--; 602 } 603 604 if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) { 605 ehea_h_free_resource(adapter->handle, 606 mr->handle, FORCE_FREE); 607 ehea_error("register_rpage_mr failed"); 608 ret = -EIO; 609 goto out; 610 } 611 } 612 613 if (hret != H_SUCCESS) { 614 ehea_h_free_resource(adapter->handle, mr->handle, 615 FORCE_FREE); 616 ehea_error("register_rpage failed for last page"); 617 ret = -EIO; 618 goto out; 619 } 620 621 mr->adapter = adapter; 622 ret = 0; 623out: 624 kfree(pt); 625 return ret; 626} 627 628int ehea_rem_mr(struct ehea_mr *mr) 629{ 630 u64 hret; 631 632 if (!mr || !mr->adapter) 633 return -EINVAL; 634 635 hret = ehea_h_free_resource(mr->adapter->handle, mr->handle, 636 FORCE_FREE); 637 if (hret != H_SUCCESS) { 638 ehea_error("destroy MR failed"); 639 return -EIO; 640 } 641 642 return 0; 643} 644 645int ehea_gen_smr(struct ehea_adapter *adapter, struct ehea_mr *old_mr, 646 struct ehea_mr *shared_mr) 647{ 648 u64 hret; 649 650 hret = ehea_h_register_smr(adapter->handle, old_mr->handle, 651 old_mr->vaddr, EHEA_MR_ACC_CTRL, 652 adapter->pd, shared_mr); 653 if (hret != H_SUCCESS) 654 return -EIO; 655 656 shared_mr->adapter = adapter; 657 658 return 0; 659} 660 661void print_error_data(u64 *data) 662{ 663 int length; 664 u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]); 665 u64 resource = data[1]; 666 667 length = EHEA_BMASK_GET(ERROR_DATA_LENGTH, data[0]); 668 669 if (length > EHEA_PAGESIZE) 670 length = EHEA_PAGESIZE; 671 672 if (type == 0x8) /* Queue Pair */ 673 ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, " 674 "port=%lX", resource, data[6], data[12], data[22]); 675 676 if (type == 0x4) /* Completion Queue */ 677 ehea_error("CQ (resource=%lX) state: AER=0x%lX", resource, 678 data[6]); 679 680 if (type == 0x3) /* Event Queue */ 681 ehea_error("EQ (resource=%lX) state: AER=0x%lX", resource, 682 data[6]); 683 684 ehea_dump(data, length, "error data"); 685} 686 687void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle) 688{ 689 unsigned long ret; 690 u64 *rblock; 691 692 rblock = kzalloc(PAGE_SIZE, GFP_KERNEL); 693 if (!rblock) { 694 ehea_error("Cannot allocate rblock memory."); 695 return; 696 } 697 698 ret = ehea_h_error_data(adapter->handle, 699 res_handle, 700 rblock); 701 702 if (ret == H_R_STATE) 703 ehea_error("No error data is available: %lX.", res_handle); 704 else if (ret == H_SUCCESS) 705 print_error_data(rblock); 706 else 707 ehea_error("Error data could not be fetched: %lX", res_handle); 708 709 kfree(rblock); 710} 711