[PATCH] IB/mthca: Factor out common queue alloc code

Clean up the allocation of memory for queues by factoring out the
common code into mthca_buf_alloc() and mthca_buf_free(). Now CQs and
QPs share the same queue allocation code, which we'll also use for SRQs.

Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by

Roland Dreier and committed by
Roland Dreier
87b81670 f520ba5a

+141 -224
+116
drivers/infiniband/hw/mthca/mthca_allocator.c
··· 177 177 178 178 kfree(array->page_list); 179 179 } 180 + 181 + /* 182 + * Handling for queue buffers -- we allocate a bunch of memory and 183 + * register it in a memory region at HCA virtual address 0. If the 184 + * requested size is > max_direct, we split the allocation into 185 + * multiple pages, so we don't require too much contiguous memory. 186 + */ 187 + 188 + int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct, 189 + union mthca_buf *buf, int *is_direct, struct mthca_pd *pd, 190 + int hca_write, struct mthca_mr *mr) 191 + { 192 + int err = -ENOMEM; 193 + int npages, shift; 194 + u64 *dma_list = NULL; 195 + dma_addr_t t; 196 + int i; 197 + 198 + if (size <= max_direct) { 199 + *is_direct = 1; 200 + npages = 1; 201 + shift = get_order(size) + PAGE_SHIFT; 202 + 203 + buf->direct.buf = dma_alloc_coherent(&dev->pdev->dev, 204 + size, &t, GFP_KERNEL); 205 + if (!buf->direct.buf) 206 + return -ENOMEM; 207 + 208 + pci_unmap_addr_set(&buf->direct, mapping, t); 209 + 210 + memset(buf->direct.buf, 0, size); 211 + 212 + while (t & ((1 << shift) - 1)) { 213 + --shift; 214 + npages *= 2; 215 + } 216 + 217 + dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); 218 + if (!dma_list) 219 + goto err_free; 220 + 221 + for (i = 0; i < npages; ++i) 222 + dma_list[i] = t + i * (1 << shift); 223 + } else { 224 + *is_direct = 0; 225 + npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; 226 + shift = PAGE_SHIFT; 227 + 228 + dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); 229 + if (!dma_list) 230 + return -ENOMEM; 231 + 232 + buf->page_list = kmalloc(npages * sizeof *buf->page_list, 233 + GFP_KERNEL); 234 + if (!buf->page_list) 235 + goto err_out; 236 + 237 + for (i = 0; i < npages; ++i) 238 + buf->page_list[i].buf = NULL; 239 + 240 + for (i = 0; i < npages; ++i) { 241 + buf->page_list[i].buf = 242 + dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, 243 + &t, GFP_KERNEL); 244 + if (!buf->page_list[i].buf) 245 + goto err_free; 246 + 247 + dma_list[i] = t; 248 + pci_unmap_addr_set(&buf->page_list[i], mapping, t); 249 + 250 + memset(buf->page_list[i].buf, 0, PAGE_SIZE); 251 + } 252 + } 253 + 254 + err = mthca_mr_alloc_phys(dev, pd->pd_num, 255 + dma_list, shift, npages, 256 + 0, size, 257 + MTHCA_MPT_FLAG_LOCAL_READ | 258 + (hca_write ? MTHCA_MPT_FLAG_LOCAL_WRITE : 0), 259 + mr); 260 + if (err) 261 + goto err_free; 262 + 263 + kfree(dma_list); 264 + 265 + return 0; 266 + 267 + err_free: 268 + mthca_buf_free(dev, size, buf, *is_direct, NULL); 269 + 270 + err_out: 271 + kfree(dma_list); 272 + 273 + return err; 274 + } 275 + 276 + void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf, 277 + int is_direct, struct mthca_mr *mr) 278 + { 279 + int i; 280 + 281 + if (mr) 282 + mthca_free_mr(dev, mr); 283 + 284 + if (is_direct) 285 + dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf, 286 + pci_unmap_addr(&buf->direct, mapping)); 287 + else { 288 + for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i) 289 + dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, 290 + buf->page_list[i].buf, 291 + pci_unmap_addr(&buf->page_list[i], 292 + mapping)); 293 + kfree(buf->page_list); 294 + } 295 + }
+6 -112
drivers/infiniband/hw/mthca/mthca_cq.c
··· 639 639 640 640 static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq) 641 641 { 642 - int i; 643 - int size; 644 - 645 - if (cq->is_direct) 646 - dma_free_coherent(&dev->pdev->dev, 647 - (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE, 648 - cq->queue.direct.buf, 649 - pci_unmap_addr(&cq->queue.direct, 650 - mapping)); 651 - else { 652 - size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE; 653 - for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i) 654 - if (cq->queue.page_list[i].buf) 655 - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, 656 - cq->queue.page_list[i].buf, 657 - pci_unmap_addr(&cq->queue.page_list[i], 658 - mapping)); 659 - 660 - kfree(cq->queue.page_list); 661 - } 662 - } 663 - 664 - static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size, 665 - struct mthca_cq *cq) 666 - { 667 - int err = -ENOMEM; 668 - int npages, shift; 669 - u64 *dma_list = NULL; 670 - dma_addr_t t; 671 - int i; 672 - 673 - if (size <= MTHCA_MAX_DIRECT_CQ_SIZE) { 674 - cq->is_direct = 1; 675 - npages = 1; 676 - shift = get_order(size) + PAGE_SHIFT; 677 - 678 - cq->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, 679 - size, &t, GFP_KERNEL); 680 - if (!cq->queue.direct.buf) 681 - return -ENOMEM; 682 - 683 - pci_unmap_addr_set(&cq->queue.direct, mapping, t); 684 - 685 - memset(cq->queue.direct.buf, 0, size); 686 - 687 - while (t & ((1 << shift) - 1)) { 688 - --shift; 689 - npages *= 2; 690 - } 691 - 692 - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); 693 - if (!dma_list) 694 - goto err_free; 695 - 696 - for (i = 0; i < npages; ++i) 697 - dma_list[i] = t + i * (1 << shift); 698 - } else { 699 - cq->is_direct = 0; 700 - npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; 701 - shift = PAGE_SHIFT; 702 - 703 - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); 704 - if (!dma_list) 705 - return -ENOMEM; 706 - 707 - cq->queue.page_list = kmalloc(npages * sizeof *cq->queue.page_list, 708 - GFP_KERNEL); 709 - if (!cq->queue.page_list) 710 - goto err_out; 711 - 712 - for (i = 0; i < npages; ++i) 713 - cq->queue.page_list[i].buf = NULL; 714 - 715 - for (i = 0; i < npages; ++i) { 716 - cq->queue.page_list[i].buf = 717 - dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, 718 - &t, GFP_KERNEL); 719 - if (!cq->queue.page_list[i].buf) 720 - goto err_free; 721 - 722 - dma_list[i] = t; 723 - pci_unmap_addr_set(&cq->queue.page_list[i], mapping, t); 724 - 725 - memset(cq->queue.page_list[i].buf, 0, PAGE_SIZE); 726 - } 727 - } 728 - 729 - err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num, 730 - dma_list, shift, npages, 731 - 0, size, 732 - MTHCA_MPT_FLAG_LOCAL_WRITE | 733 - MTHCA_MPT_FLAG_LOCAL_READ, 734 - &cq->mr); 735 - if (err) 736 - goto err_free; 737 - 738 - kfree(dma_list); 739 - 740 - return 0; 741 - 742 - err_free: 743 - mthca_free_cq_buf(dev, cq); 744 - 745 - err_out: 746 - kfree(dma_list); 747 - 748 - return err; 642 + mthca_buf_free(dev, (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE, 643 + &cq->queue, cq->is_direct, &cq->mr); 749 644 } 750 645 751 646 int mthca_init_cq(struct mthca_dev *dev, int nent, ··· 692 797 cq_context = mailbox->buf; 693 798 694 799 if (cq->is_kernel) { 695 - err = mthca_alloc_cq_buf(dev, size, cq); 800 + err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_CQ_SIZE, 801 + &cq->queue, &cq->is_direct, 802 + &dev->driver_pd, 1, &cq->mr); 696 803 if (err) 697 804 goto err_out_mailbox; 698 805 ··· 755 858 return 0; 756 859 757 860 err_out_free_mr: 758 - if (cq->is_kernel) { 759 - mthca_free_mr(dev, &cq->mr); 861 + if (cq->is_kernel) 760 862 mthca_free_cq_buf(dev, cq); 761 - } 762 863 763 864 err_out_mailbox: 764 865 mthca_free_mailbox(dev, mailbox); ··· 824 929 wait_event(cq->wait, !atomic_read(&cq->refcount)); 825 930 826 931 if (cq->is_kernel) { 827 - mthca_free_mr(dev, &cq->mr); 828 932 mthca_free_cq_buf(dev, cq); 829 933 if (mthca_is_memfree(dev)) { 830 934 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
+5
drivers/infiniband/hw/mthca/mthca_dev.h
··· 361 361 void mthca_array_clear(struct mthca_array *array, int index); 362 362 int mthca_array_init(struct mthca_array *array, int nent); 363 363 void mthca_array_cleanup(struct mthca_array *array, int nent); 364 + int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct, 365 + union mthca_buf *buf, int *is_direct, struct mthca_pd *pd, 366 + int hca_write, struct mthca_mr *mr); 367 + void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf, 368 + int is_direct, struct mthca_mr *mr); 364 369 365 370 int mthca_init_uar_table(struct mthca_dev *dev); 366 371 int mthca_init_pd_table(struct mthca_dev *dev);
+7 -8
drivers/infiniband/hw/mthca/mthca_provider.h
··· 51 51 DECLARE_PCI_UNMAP_ADDR(mapping) 52 52 }; 53 53 54 + union mthca_buf { 55 + struct mthca_buf_list direct; 56 + struct mthca_buf_list *page_list; 57 + }; 58 + 54 59 struct mthca_uar { 55 60 unsigned long pfn; 56 61 int index; ··· 192 187 __be32 *arm_db; 193 188 int arm_sn; 194 189 195 - union { 196 - struct mthca_buf_list direct; 197 - struct mthca_buf_list *page_list; 198 - } queue; 190 + union mthca_buf queue; 199 191 struct mthca_mr mr; 200 192 wait_queue_head_t wait; 201 193 }; ··· 230 228 int send_wqe_offset; 231 229 232 230 u64 *wrid; 233 - union { 234 - struct mthca_buf_list direct; 235 - struct mthca_buf_list *page_list; 236 - } queue; 231 + union mthca_buf queue; 237 232 238 233 wait_queue_head_t wait; 239 234 };
+7 -104
drivers/infiniband/hw/mthca/mthca_qp.c
··· 926 926 struct mthca_qp *qp) 927 927 { 928 928 int size; 929 - int i; 930 - int npages, shift; 931 - dma_addr_t t; 932 - u64 *dma_list = NULL; 933 929 int err = -ENOMEM; 934 930 935 931 size = sizeof (struct mthca_next_seg) + ··· 975 979 if (!qp->wrid) 976 980 goto err_out; 977 981 978 - if (size <= MTHCA_MAX_DIRECT_QP_SIZE) { 979 - qp->is_direct = 1; 980 - npages = 1; 981 - shift = get_order(size) + PAGE_SHIFT; 982 - 983 - if (0) 984 - mthca_dbg(dev, "Creating direct QP of size %d (shift %d)\n", 985 - size, shift); 986 - 987 - qp->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, size, 988 - &t, GFP_KERNEL); 989 - if (!qp->queue.direct.buf) 990 - goto err_out; 991 - 992 - pci_unmap_addr_set(&qp->queue.direct, mapping, t); 993 - 994 - memset(qp->queue.direct.buf, 0, size); 995 - 996 - while (t & ((1 << shift) - 1)) { 997 - --shift; 998 - npages *= 2; 999 - } 1000 - 1001 - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); 1002 - if (!dma_list) 1003 - goto err_out_free; 1004 - 1005 - for (i = 0; i < npages; ++i) 1006 - dma_list[i] = t + i * (1 << shift); 1007 - } else { 1008 - qp->is_direct = 0; 1009 - npages = size / PAGE_SIZE; 1010 - shift = PAGE_SHIFT; 1011 - 1012 - if (0) 1013 - mthca_dbg(dev, "Creating indirect QP with %d pages\n", npages); 1014 - 1015 - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); 1016 - if (!dma_list) 1017 - goto err_out; 1018 - 1019 - qp->queue.page_list = kmalloc(npages * 1020 - sizeof *qp->queue.page_list, 1021 - GFP_KERNEL); 1022 - if (!qp->queue.page_list) 1023 - goto err_out; 1024 - 1025 - for (i = 0; i < npages; ++i) { 1026 - qp->queue.page_list[i].buf = 1027 - dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, 1028 - &t, GFP_KERNEL); 1029 - if (!qp->queue.page_list[i].buf) 1030 - goto err_out_free; 1031 - 1032 - memset(qp->queue.page_list[i].buf, 0, PAGE_SIZE); 1033 - 1034 - pci_unmap_addr_set(&qp->queue.page_list[i], mapping, t); 1035 - dma_list[i] = t; 1036 - } 1037 - } 1038 - 1039 - err = mthca_mr_alloc_phys(dev, pd->pd_num, dma_list, shift, 1040 - npages, 0, size, 1041 - MTHCA_MPT_FLAG_LOCAL_READ, 1042 - &qp->mr); 982 + err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_QP_SIZE, 983 + &qp->queue, &qp->is_direct, pd, 0, &qp->mr); 1043 984 if (err) 1044 - goto err_out_free; 985 + goto err_out; 1045 986 1046 - kfree(dma_list); 1047 987 return 0; 1048 988 1049 - err_out_free: 1050 - if (qp->is_direct) { 1051 - dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf, 1052 - pci_unmap_addr(&qp->queue.direct, mapping)); 1053 - } else 1054 - for (i = 0; i < npages; ++i) { 1055 - if (qp->queue.page_list[i].buf) 1056 - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, 1057 - qp->queue.page_list[i].buf, 1058 - pci_unmap_addr(&qp->queue.page_list[i], 1059 - mapping)); 1060 - 1061 - } 1062 - 1063 - err_out: 989 + err_out: 1064 990 kfree(qp->wrid); 1065 - kfree(dma_list); 1066 991 return err; 1067 992 } 1068 993 1069 994 static void mthca_free_wqe_buf(struct mthca_dev *dev, 1070 995 struct mthca_qp *qp) 1071 996 { 1072 - int i; 1073 - int size = PAGE_ALIGN(qp->send_wqe_offset + 1074 - (qp->sq.max << qp->sq.wqe_shift)); 1075 - 1076 - if (qp->is_direct) { 1077 - dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf, 1078 - pci_unmap_addr(&qp->queue.direct, mapping)); 1079 - } else { 1080 - for (i = 0; i < size / PAGE_SIZE; ++i) { 1081 - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, 1082 - qp->queue.page_list[i].buf, 1083 - pci_unmap_addr(&qp->queue.page_list[i], 1084 - mapping)); 1085 - } 1086 - } 1087 - 997 + mthca_buf_free(dev, PAGE_ALIGN(qp->send_wqe_offset + 998 + (qp->sq.max << qp->sq.wqe_shift)), 999 + &qp->queue, qp->is_direct, &qp->mr); 1088 1000 kfree(qp->wrid); 1089 1001 } 1090 1002 ··· 1337 1433 if (qp->ibqp.send_cq != qp->ibqp.recv_cq) 1338 1434 mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn); 1339 1435 1340 - mthca_free_mr(dev, &qp->mr); 1341 1436 mthca_free_memfree(dev, qp); 1342 1437 mthca_free_wqe_buf(dev, qp); 1343 1438 }