Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RDMA/qedr: Add doorbell overflow recovery support

Use the doorbell recovery mechanism to register rdma related doorbells
that will be restored in case there is a doorbell overflow attention.

Link: https://lore.kernel.org/r/20191030094417.16866-8-michal.kalderon@marvell.com
Signed-off-by: Ariel Elior <ariel.elior@marvell.com>
Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>

authored by

Michal Kalderon and committed by
Jason Gunthorpe
97f61250 4c6bb02d

+300 -50
+10 -1
drivers/infiniband/hw/qedr/qedr.h
··· 235 235 u64 dpi_phys_addr; 236 236 u32 dpi_size; 237 237 u16 dpi; 238 + bool db_rec; 238 239 }; 239 240 240 241 union db_prod64 { ··· 263 262 struct qedr_pbl *pbl_tbl; 264 263 u64 buf_addr; 265 264 size_t buf_len; 265 + 266 + /* doorbell recovery */ 267 + void __iomem *db_addr; 268 + struct qedr_user_db_rec *db_rec_data; 269 + struct rdma_user_mmap_entry *db_mmap_entry; 266 270 }; 267 271 268 272 struct qedr_cq { ··· 488 482 struct qedr_user_mmap_entry { 489 483 struct rdma_user_mmap_entry rdma_entry; 490 484 struct qedr_dev *dev; 491 - u64 io_address; 485 + union { 486 + u64 io_address; 487 + void *address; 488 + }; 492 489 size_t length; 493 490 u16 dpi; 494 491 u8 mmap_flag;
+265 -49
drivers/infiniband/hw/qedr/verbs.c
··· 61 61 62 62 enum { 63 63 QEDR_USER_MMAP_IO_WC = 0, 64 + QEDR_USER_MMAP_PHYS_PAGE, 64 65 }; 65 66 66 67 static inline int qedr_ib_copy_to_udata(struct ib_udata *udata, void *src, ··· 268 267 int rc; 269 268 struct qedr_ucontext *ctx = get_qedr_ucontext(uctx); 270 269 struct qedr_alloc_ucontext_resp uresp = {}; 270 + struct qedr_alloc_ucontext_req ureq = {}; 271 271 struct qedr_dev *dev = get_qedr_dev(ibdev); 272 272 struct qed_rdma_add_user_out_params oparams; 273 273 struct qedr_user_mmap_entry *entry; 274 274 275 275 if (!udata) 276 276 return -EFAULT; 277 + 278 + if (udata->inlen) { 279 + rc = ib_copy_from_udata(&ureq, udata, 280 + min(sizeof(ureq), udata->inlen)); 281 + if (rc) { 282 + DP_ERR(dev, "Problem copying data from user space\n"); 283 + return -EFAULT; 284 + } 285 + 286 + ctx->db_rec = !!(ureq.context_flags & QEDR_ALLOC_UCTX_DB_REC); 287 + } 277 288 278 289 rc = dev->ops->rdma_add_user(dev->rdma_ctx, &oparams); 279 290 if (rc) { ··· 365 352 struct qedr_user_mmap_entry *entry = get_qedr_mmap_entry(rdma_entry); 366 353 struct qedr_dev *dev = entry->dev; 367 354 368 - if (entry->mmap_flag == QEDR_USER_MMAP_IO_WC) 355 + if (entry->mmap_flag == QEDR_USER_MMAP_PHYS_PAGE) 356 + free_page((unsigned long)entry->address); 357 + else if (entry->mmap_flag == QEDR_USER_MMAP_IO_WC) 369 358 dev->ops->rdma_remove_user(dev->rdma_ctx, entry->dpi); 370 359 371 360 kfree(entry); ··· 403 388 rc = rdma_user_mmap_io(ucontext, vma, pfn, length, 404 389 pgprot_writecombine(vma->vm_page_prot), 405 390 rdma_entry); 391 + break; 392 + case QEDR_USER_MMAP_PHYS_PAGE: 393 + rc = vm_insert_page(vma, vma->vm_start, 394 + virt_to_page(entry->address)); 406 395 break; 407 396 default: 408 397 rc = -EINVAL; ··· 648 629 } 649 630 } 650 631 632 + static int qedr_db_recovery_add(struct qedr_dev *dev, 633 + void __iomem *db_addr, 634 + void *db_data, 635 + enum qed_db_rec_width db_width, 636 + enum qed_db_rec_space db_space) 637 + { 638 + if (!db_data) { 639 + DP_DEBUG(dev, QEDR_MSG_INIT, "avoiding db rec since old lib\n"); 640 + return 0; 641 + } 642 + 643 + return dev->ops->common->db_recovery_add(dev->cdev, db_addr, db_data, 644 + db_width, db_space); 645 + } 646 + 647 + static void qedr_db_recovery_del(struct qedr_dev *dev, 648 + void __iomem *db_addr, 649 + void *db_data) 650 + { 651 + if (!db_data) { 652 + DP_DEBUG(dev, QEDR_MSG_INIT, "avoiding db rec since old lib\n"); 653 + return; 654 + } 655 + 656 + /* Ignore return code as there is not much we can do about it. Error 657 + * log will be printed inside. 658 + */ 659 + dev->ops->common->db_recovery_del(dev->cdev, db_addr, db_data); 660 + } 661 + 651 662 static int qedr_copy_cq_uresp(struct qedr_dev *dev, 652 - struct qedr_cq *cq, struct ib_udata *udata) 663 + struct qedr_cq *cq, struct ib_udata *udata, 664 + u32 db_offset) 653 665 { 654 666 struct qedr_create_cq_uresp uresp; 655 667 int rc; 656 668 657 669 memset(&uresp, 0, sizeof(uresp)); 658 670 659 - uresp.db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT); 671 + uresp.db_offset = db_offset; 660 672 uresp.icid = cq->icid; 673 + uresp.db_rec_addr = rdma_user_mmap_get_offset(cq->q.db_mmap_entry); 661 674 662 675 rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp)); 663 676 if (rc) ··· 717 666 return aligned_size / QEDR_CQE_SIZE; 718 667 } 719 668 669 + static int qedr_init_user_db_rec(struct ib_udata *udata, 670 + struct qedr_dev *dev, struct qedr_userq *q, 671 + bool requires_db_rec) 672 + { 673 + struct qedr_ucontext *uctx = 674 + rdma_udata_to_drv_context(udata, struct qedr_ucontext, 675 + ibucontext); 676 + struct qedr_user_mmap_entry *entry; 677 + int rc; 678 + 679 + /* Aborting for non doorbell userqueue (SRQ) or non-supporting lib */ 680 + if (requires_db_rec == 0 || !uctx->db_rec) 681 + return 0; 682 + 683 + /* Allocate a page for doorbell recovery, add to mmap */ 684 + q->db_rec_data = (void *)get_zeroed_page(GFP_USER); 685 + if (!q->db_rec_data) { 686 + DP_ERR(dev, "get_zeroed_page failed\n"); 687 + return -ENOMEM; 688 + } 689 + 690 + entry = kzalloc(sizeof(*entry), GFP_KERNEL); 691 + if (!entry) 692 + goto err_free_db_data; 693 + 694 + entry->address = q->db_rec_data; 695 + entry->length = PAGE_SIZE; 696 + entry->mmap_flag = QEDR_USER_MMAP_PHYS_PAGE; 697 + rc = rdma_user_mmap_entry_insert(&uctx->ibucontext, 698 + &entry->rdma_entry, 699 + PAGE_SIZE); 700 + if (rc) 701 + goto err_free_entry; 702 + 703 + q->db_mmap_entry = &entry->rdma_entry; 704 + 705 + return 0; 706 + 707 + err_free_entry: 708 + kfree(entry); 709 + 710 + err_free_db_data: 711 + free_page((unsigned long)q->db_rec_data); 712 + q->db_rec_data = NULL; 713 + return -ENOMEM; 714 + } 715 + 720 716 static inline int qedr_init_user_queue(struct ib_udata *udata, 721 717 struct qedr_dev *dev, 722 718 struct qedr_userq *q, u64 buf_addr, 723 - size_t buf_len, int access, int dmasync, 719 + size_t buf_len, bool requires_db_rec, 720 + int access, int dmasync, 724 721 int alloc_and_init) 725 722 { 726 723 u32 fw_pages; ··· 806 707 } 807 708 } 808 709 809 - return 0; 710 + /* mmap the user address used to store doorbell data for recovery */ 711 + return qedr_init_user_db_rec(udata, dev, q, requires_db_rec); 810 712 811 713 err0: 812 714 ib_umem_release(q->umem); ··· 893 793 int entries = attr->cqe; 894 794 struct qedr_cq *cq = get_qedr_cq(ibcq); 895 795 int chain_entries; 796 + u32 db_offset; 896 797 int page_cnt; 897 798 u64 pbl_ptr; 898 799 u16 icid; ··· 913 812 chain_entries = qedr_align_cq_entries(entries); 914 813 chain_entries = min_t(int, chain_entries, QEDR_MAX_CQES); 915 814 815 + /* calc db offset. user will add DPI base, kernel will add db addr */ 816 + db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT); 817 + 916 818 if (udata) { 917 - if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) { 819 + if (ib_copy_from_udata(&ureq, udata, min(sizeof(ureq), 820 + udata->inlen))) { 918 821 DP_ERR(dev, 919 822 "create cq: problem copying data from user space\n"); 920 823 goto err0; ··· 933 828 cq->cq_type = QEDR_CQ_TYPE_USER; 934 829 935 830 rc = qedr_init_user_queue(udata, dev, &cq->q, ureq.addr, 936 - ureq.len, IB_ACCESS_LOCAL_WRITE, 1, 937 - 1); 831 + ureq.len, true, 832 + IB_ACCESS_LOCAL_WRITE, 833 + 1, 1); 938 834 if (rc) 939 835 goto err0; 940 836 ··· 943 837 page_cnt = cq->q.pbl_info.num_pbes; 944 838 945 839 cq->ibcq.cqe = chain_entries; 840 + cq->q.db_addr = ctx->dpi_addr + db_offset; 946 841 } else { 947 842 cq->cq_type = QEDR_CQ_TYPE_KERNEL; 948 843 ··· 955 848 sizeof(union rdma_cqe), 956 849 &cq->pbl, NULL); 957 850 if (rc) 958 - goto err1; 851 + goto err0; 959 852 960 853 page_cnt = qed_chain_get_page_cnt(&cq->pbl); 961 854 pbl_ptr = qed_chain_get_pbl_phys(&cq->pbl); ··· 967 860 968 861 rc = dev->ops->rdma_create_cq(dev->rdma_ctx, &params, &icid); 969 862 if (rc) 970 - goto err2; 863 + goto err1; 971 864 972 865 cq->icid = icid; 973 866 cq->sig = QEDR_CQ_MAGIC_NUMBER; 974 867 spin_lock_init(&cq->cq_lock); 975 868 976 869 if (udata) { 977 - rc = qedr_copy_cq_uresp(dev, cq, udata); 870 + rc = qedr_copy_cq_uresp(dev, cq, udata, db_offset); 978 871 if (rc) 979 - goto err3; 872 + goto err2; 873 + 874 + rc = qedr_db_recovery_add(dev, cq->q.db_addr, 875 + &cq->q.db_rec_data->db_data, 876 + DB_REC_WIDTH_64B, 877 + DB_REC_USER); 878 + if (rc) 879 + goto err2; 880 + 980 881 } else { 981 882 /* Generate doorbell address. */ 982 - cq->db_addr = dev->db_addr + 983 - DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT); 984 883 cq->db.data.icid = cq->icid; 884 + cq->db_addr = dev->db_addr + db_offset; 985 885 cq->db.data.params = DB_AGG_CMD_SET << 986 886 RDMA_PWM_VAL32_DATA_AGG_CMD_SHIFT; 987 887 ··· 998 884 cq->latest_cqe = NULL; 999 885 consume_cqe(cq); 1000 886 cq->cq_cons = qed_chain_get_cons_idx_u32(&cq->pbl); 887 + 888 + rc = qedr_db_recovery_add(dev, cq->db_addr, &cq->db.data, 889 + DB_REC_WIDTH_64B, DB_REC_KERNEL); 890 + if (rc) 891 + goto err2; 1001 892 } 1002 893 1003 894 DP_DEBUG(dev, QEDR_MSG_CQ, ··· 1011 892 1012 893 return 0; 1013 894 1014 - err3: 895 + err2: 1015 896 destroy_iparams.icid = cq->icid; 1016 897 dev->ops->rdma_destroy_cq(dev->rdma_ctx, &destroy_iparams, 1017 898 &destroy_oparams); 1018 - err2: 1019 - if (udata) 1020 - qedr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl); 1021 - else 1022 - dev->ops->common->chain_free(dev->cdev, &cq->pbl); 1023 899 err1: 1024 - if (udata) 900 + if (udata) { 901 + qedr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl); 1025 902 ib_umem_release(cq->q.umem); 903 + if (ctx) 904 + rdma_user_mmap_entry_remove(cq->q.db_mmap_entry); 905 + } else { 906 + dev->ops->common->chain_free(dev->cdev, &cq->pbl); 907 + } 1026 908 err0: 1027 909 return -EINVAL; 1028 910 } ··· 1054 934 cq->destroyed = 1; 1055 935 1056 936 /* GSIs CQs are handled by driver, so they don't exist in the FW */ 1057 - if (cq->cq_type == QEDR_CQ_TYPE_GSI) 937 + if (cq->cq_type == QEDR_CQ_TYPE_GSI) { 938 + qedr_db_recovery_del(dev, cq->db_addr, &cq->db.data); 1058 939 return; 940 + } 1059 941 1060 942 iparams.icid = cq->icid; 1061 943 dev->ops->rdma_destroy_cq(dev->rdma_ctx, &iparams, &oparams); ··· 1066 944 if (udata) { 1067 945 qedr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl); 1068 946 ib_umem_release(cq->q.umem); 947 + 948 + if (cq->q.db_rec_data) { 949 + qedr_db_recovery_del(dev, cq->q.db_addr, 950 + &cq->q.db_rec_data->db_data); 951 + rdma_user_mmap_entry_remove(cq->q.db_mmap_entry); 952 + } 953 + } else { 954 + qedr_db_recovery_del(dev, cq->db_addr, &cq->db.data); 1069 955 } 1070 956 1071 957 /* We don't want the IRQ handler to handle a non-existing CQ so we ··· 1238 1108 } 1239 1109 1240 1110 static void qedr_copy_rq_uresp(struct qedr_dev *dev, 1241 - struct qedr_create_qp_uresp *uresp, 1242 - struct qedr_qp *qp) 1111 + struct qedr_create_qp_uresp *uresp, 1112 + struct qedr_qp *qp) 1243 1113 { 1244 1114 /* iWARP requires two doorbells per RQ. */ 1245 1115 if (rdma_protocol_iwarp(&dev->ibdev, 1)) { ··· 1252 1122 } 1253 1123 1254 1124 uresp->rq_icid = qp->icid; 1125 + uresp->rq_db_rec_addr = rdma_user_mmap_get_offset(qp->urq.db_mmap_entry); 1255 1126 } 1256 1127 1257 1128 static void qedr_copy_sq_uresp(struct qedr_dev *dev, ··· 1266 1135 uresp->sq_icid = qp->icid; 1267 1136 else 1268 1137 uresp->sq_icid = qp->icid + 1; 1138 + 1139 + uresp->sq_db_rec_addr = 1140 + rdma_user_mmap_get_offset(qp->usq.db_mmap_entry); 1269 1141 } 1270 1142 1271 1143 static int qedr_copy_qp_uresp(struct qedr_dev *dev, 1272 - struct qedr_qp *qp, struct ib_udata *udata) 1144 + struct qedr_qp *qp, struct ib_udata *udata, 1145 + struct qedr_create_qp_uresp *uresp) 1273 1146 { 1274 - struct qedr_create_qp_uresp uresp; 1275 1147 int rc; 1276 1148 1277 - memset(&uresp, 0, sizeof(uresp)); 1278 - qedr_copy_sq_uresp(dev, &uresp, qp); 1279 - qedr_copy_rq_uresp(dev, &uresp, qp); 1149 + memset(uresp, 0, sizeof(*uresp)); 1150 + qedr_copy_sq_uresp(dev, uresp, qp); 1151 + qedr_copy_rq_uresp(dev, uresp, qp); 1280 1152 1281 - uresp.atomic_supported = dev->atomic_cap != IB_ATOMIC_NONE; 1282 - uresp.qp_id = qp->qp_id; 1153 + uresp->atomic_supported = dev->atomic_cap != IB_ATOMIC_NONE; 1154 + uresp->qp_id = qp->qp_id; 1283 1155 1284 - rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp)); 1156 + rc = qedr_ib_copy_to_udata(udata, uresp, sizeof(*uresp)); 1285 1157 if (rc) 1286 1158 DP_ERR(dev, 1287 1159 "create qp: failed a copy to user space with qp icid=0x%x.\n", ··· 1331 1197 qp->sq.max_sges, qp->sq_cq->icid); 1332 1198 } 1333 1199 1334 - static void qedr_set_roce_db_info(struct qedr_dev *dev, struct qedr_qp *qp) 1200 + static int qedr_set_roce_db_info(struct qedr_dev *dev, struct qedr_qp *qp) 1335 1201 { 1202 + int rc; 1203 + 1336 1204 qp->sq.db = dev->db_addr + 1337 1205 DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD); 1338 1206 qp->sq.db_data.data.icid = qp->icid + 1; 1207 + rc = qedr_db_recovery_add(dev, qp->sq.db, 1208 + &qp->sq.db_data, 1209 + DB_REC_WIDTH_32B, 1210 + DB_REC_KERNEL); 1211 + if (rc) 1212 + return rc; 1213 + 1339 1214 if (!qp->srq) { 1340 1215 qp->rq.db = dev->db_addr + 1341 1216 DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_ROCE_RQ_PROD); 1342 1217 qp->rq.db_data.data.icid = qp->icid; 1218 + 1219 + rc = qedr_db_recovery_add(dev, qp->rq.db, 1220 + &qp->rq.db_data, 1221 + DB_REC_WIDTH_32B, 1222 + DB_REC_KERNEL); 1223 + if (rc) 1224 + qedr_db_recovery_del(dev, qp->sq.db, 1225 + &qp->sq.db_data); 1343 1226 } 1227 + 1228 + return rc; 1344 1229 } 1345 1230 1346 1231 static int qedr_check_srq_params(struct qedr_dev *dev, ··· 1413 1260 int rc; 1414 1261 1415 1262 rc = qedr_init_user_queue(udata, srq->dev, &srq->usrq, ureq->srq_addr, 1416 - ureq->srq_len, access, dmasync, 1); 1263 + ureq->srq_len, false, access, dmasync, 1); 1417 1264 if (rc) 1418 1265 return rc; 1419 1266 ··· 1509 1356 hw_srq->max_sges = init_attr->attr.max_sge; 1510 1357 1511 1358 if (udata) { 1512 - if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) { 1359 + if (ib_copy_from_udata(&ureq, udata, min(sizeof(ureq), 1360 + udata->inlen))) { 1513 1361 DP_ERR(dev, 1514 1362 "create srq: problem copying data from user space\n"); 1515 1363 goto err0; ··· 1699 1545 &qp->urq.pbl_info, FW_PAGE_SHIFT); 1700 1546 } 1701 1547 1702 - static void qedr_cleanup_user(struct qedr_dev *dev, struct qedr_qp *qp) 1548 + static void qedr_cleanup_user(struct qedr_dev *dev, 1549 + struct qedr_ucontext *ctx, 1550 + struct qedr_qp *qp) 1703 1551 { 1704 1552 ib_umem_release(qp->usq.umem); 1705 1553 qp->usq.umem = NULL; ··· 1716 1560 kfree(qp->usq.pbl_tbl); 1717 1561 kfree(qp->urq.pbl_tbl); 1718 1562 } 1563 + 1564 + if (qp->usq.db_rec_data) { 1565 + qedr_db_recovery_del(dev, qp->usq.db_addr, 1566 + &qp->usq.db_rec_data->db_data); 1567 + rdma_user_mmap_entry_remove(qp->usq.db_mmap_entry); 1568 + } 1569 + 1570 + if (qp->urq.db_rec_data) { 1571 + qedr_db_recovery_del(dev, qp->urq.db_addr, 1572 + &qp->urq.db_rec_data->db_data); 1573 + rdma_user_mmap_entry_remove(qp->urq.db_mmap_entry); 1574 + } 1719 1575 } 1720 1576 1721 1577 static int qedr_create_user_qp(struct qedr_dev *dev, ··· 1739 1571 struct qed_rdma_create_qp_in_params in_params; 1740 1572 struct qed_rdma_create_qp_out_params out_params; 1741 1573 struct qedr_pd *pd = get_qedr_pd(ibpd); 1574 + struct qedr_create_qp_uresp uresp; 1575 + struct qedr_ucontext *ctx = NULL; 1742 1576 struct qedr_create_qp_ureq ureq; 1743 1577 int alloc_and_init = rdma_protocol_roce(&dev->ibdev, 1); 1744 1578 int rc = -EINVAL; 1745 1579 1746 1580 qp->create_type = QEDR_QP_CREATE_USER; 1747 1581 memset(&ureq, 0, sizeof(ureq)); 1748 - rc = ib_copy_from_udata(&ureq, udata, sizeof(ureq)); 1582 + rc = ib_copy_from_udata(&ureq, udata, min(sizeof(ureq), udata->inlen)); 1749 1583 if (rc) { 1750 1584 DP_ERR(dev, "Problem copying data from user space\n"); 1751 1585 return rc; ··· 1755 1585 1756 1586 /* SQ - read access only (0), dma sync not required (0) */ 1757 1587 rc = qedr_init_user_queue(udata, dev, &qp->usq, ureq.sq_addr, 1758 - ureq.sq_len, 0, 0, alloc_and_init); 1588 + ureq.sq_len, true, 0, 0, 1589 + alloc_and_init); 1759 1590 if (rc) 1760 1591 return rc; 1761 1592 1762 1593 if (!qp->srq) { 1763 1594 /* RQ - read access only (0), dma sync not required (0) */ 1764 1595 rc = qedr_init_user_queue(udata, dev, &qp->urq, ureq.rq_addr, 1765 - ureq.rq_len, 0, 0, alloc_and_init); 1596 + ureq.rq_len, true, 1597 + 0, 0, alloc_and_init); 1766 1598 if (rc) 1767 1599 return rc; 1768 1600 } ··· 1794 1622 qp->qp_id = out_params.qp_id; 1795 1623 qp->icid = out_params.icid; 1796 1624 1797 - rc = qedr_copy_qp_uresp(dev, qp, udata); 1625 + rc = qedr_copy_qp_uresp(dev, qp, udata, &uresp); 1626 + if (rc) 1627 + goto err; 1628 + 1629 + /* db offset was calculated in copy_qp_uresp, now set in the user q */ 1630 + ctx = pd->uctx; 1631 + qp->usq.db_addr = ctx->dpi_addr + uresp.sq_db_offset; 1632 + qp->urq.db_addr = ctx->dpi_addr + uresp.rq_db_offset; 1633 + 1634 + rc = qedr_db_recovery_add(dev, qp->usq.db_addr, 1635 + &qp->usq.db_rec_data->db_data, 1636 + DB_REC_WIDTH_32B, 1637 + DB_REC_USER); 1638 + if (rc) 1639 + goto err; 1640 + 1641 + rc = qedr_db_recovery_add(dev, qp->urq.db_addr, 1642 + &qp->urq.db_rec_data->db_data, 1643 + DB_REC_WIDTH_32B, 1644 + DB_REC_USER); 1798 1645 if (rc) 1799 1646 goto err; 1800 1647 1801 1648 qedr_qp_user_print(dev, qp); 1802 1649 1803 - return 0; 1650 + return rc; 1804 1651 err: 1805 1652 rc = dev->ops->rdma_destroy_qp(dev->rdma_ctx, qp->qed_qp); 1806 1653 if (rc) 1807 1654 DP_ERR(dev, "create qp: fatal fault. rc=%d", rc); 1808 1655 1809 1656 err1: 1810 - qedr_cleanup_user(dev, qp); 1657 + qedr_cleanup_user(dev, ctx, qp); 1811 1658 return rc; 1812 1659 } 1813 1660 1814 - static void qedr_set_iwarp_db_info(struct qedr_dev *dev, struct qedr_qp *qp) 1661 + static int qedr_set_iwarp_db_info(struct qedr_dev *dev, struct qedr_qp *qp) 1815 1662 { 1663 + int rc; 1664 + 1816 1665 qp->sq.db = dev->db_addr + 1817 1666 DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD); 1818 1667 qp->sq.db_data.data.icid = qp->icid; 1668 + 1669 + rc = qedr_db_recovery_add(dev, qp->sq.db, 1670 + &qp->sq.db_data, 1671 + DB_REC_WIDTH_32B, 1672 + DB_REC_KERNEL); 1673 + if (rc) 1674 + return rc; 1819 1675 1820 1676 qp->rq.db = dev->db_addr + 1821 1677 DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_IWARP_RQ_PROD); ··· 1852 1652 DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_FLAGS); 1853 1653 qp->rq.iwarp_db2_data.data.icid = qp->icid; 1854 1654 qp->rq.iwarp_db2_data.data.value = DQ_TCM_IWARP_POST_RQ_CF_CMD; 1655 + 1656 + rc = qedr_db_recovery_add(dev, qp->rq.db, 1657 + &qp->rq.db_data, 1658 + DB_REC_WIDTH_32B, 1659 + DB_REC_KERNEL); 1660 + return rc; 1855 1661 } 1856 1662 1857 1663 static int ··· 1905 1699 qp->qp_id = out_params.qp_id; 1906 1700 qp->icid = out_params.icid; 1907 1701 1908 - qedr_set_roce_db_info(dev, qp); 1909 - return rc; 1702 + return qedr_set_roce_db_info(dev, qp); 1910 1703 } 1911 1704 1912 1705 static int ··· 1963 1758 qp->qp_id = out_params.qp_id; 1964 1759 qp->icid = out_params.icid; 1965 1760 1966 - qedr_set_iwarp_db_info(dev, qp); 1967 - return rc; 1761 + return qedr_set_iwarp_db_info(dev, qp); 1968 1762 1969 1763 err: 1970 1764 dev->ops->rdma_destroy_qp(dev->rdma_ctx, qp->qed_qp); ··· 1978 1774 1979 1775 dev->ops->common->chain_free(dev->cdev, &qp->rq.pbl); 1980 1776 kfree(qp->rqe_wr_id); 1777 + 1778 + /* GSI qp is not registered to db mechanism so no need to delete */ 1779 + if (qp->qp_type == IB_QPT_GSI) 1780 + return; 1781 + 1782 + qedr_db_recovery_del(dev, qp->sq.db, &qp->sq.db_data); 1783 + 1784 + if (!qp->srq) 1785 + qedr_db_recovery_del(dev, qp->rq.db, &qp->rq.db_data); 1981 1786 } 1982 1787 1983 1788 static int qedr_create_kernel_qp(struct qedr_dev *dev, ··· 2627 2414 static int qedr_free_qp_resources(struct qedr_dev *dev, struct qedr_qp *qp, 2628 2415 struct ib_udata *udata) 2629 2416 { 2630 - int rc = 0; 2417 + struct qedr_ucontext *ctx = 2418 + rdma_udata_to_drv_context(udata, struct qedr_ucontext, 2419 + ibucontext); 2420 + int rc; 2631 2421 2632 2422 if (qp->qp_type != IB_QPT_GSI) { 2633 2423 rc = dev->ops->rdma_destroy_qp(dev->rdma_ctx, qp->qed_qp); ··· 2639 2423 } 2640 2424 2641 2425 if (qp->create_type == QEDR_QP_CREATE_USER) 2642 - qedr_cleanup_user(dev, qp); 2426 + qedr_cleanup_user(dev, ctx, qp); 2643 2427 else 2644 2428 qedr_cleanup_kernel(dev, qp); 2645 2429
+25
include/uapi/rdma/qedr-abi.h
··· 38 38 #define QEDR_ABI_VERSION (8) 39 39 40 40 /* user kernel communication data structures. */ 41 + enum qedr_alloc_ucontext_flags { 42 + QEDR_ALLOC_UCTX_RESERVED = 1 << 0, 43 + QEDR_ALLOC_UCTX_DB_REC = 1 << 1 44 + }; 45 + 46 + struct qedr_alloc_ucontext_req { 47 + __u32 context_flags; 48 + __u32 reserved; 49 + }; 41 50 42 51 struct qedr_alloc_ucontext_resp { 43 52 __aligned_u64 db_pa; ··· 83 74 __u32 db_offset; 84 75 __u16 icid; 85 76 __u16 reserved; 77 + __aligned_u64 db_rec_addr; 86 78 }; 87 79 88 80 struct qedr_create_qp_ureq { ··· 119 109 120 110 __u32 rq_db2_offset; 121 111 __u32 reserved; 112 + 113 + /* address of SQ doorbell recovery user entry */ 114 + __aligned_u64 sq_db_rec_addr; 115 + 116 + /* address of RQ doorbell recovery user entry */ 117 + __aligned_u64 rq_db_rec_addr; 118 + 122 119 }; 123 120 124 121 struct qedr_create_srq_ureq { ··· 143 126 __u16 srq_id; 144 127 __u16 reserved0; 145 128 __u32 reserved1; 129 + }; 130 + 131 + /* doorbell recovery entry allocated and populated by userspace doorbelling 132 + * entities and mapped to kernel. Kernel uses this to register doorbell 133 + * information with doorbell drop recovery mechanism. 134 + */ 135 + struct qedr_user_db_rec { 136 + __aligned_u64 db_data; /* doorbell data */ 146 137 }; 147 138 148 139 #endif /* __QEDR_USER_H__ */