diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_qp.c | 94 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/hcp_if.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/hcp_if.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/hcp_phyp.c | 11 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/hcp_phyp.h | 2 |
5 files changed, 65 insertions, 50 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 00c108159714..ead4e718c082 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
@@ -461,7 +461,7 @@ static struct ehca_qp *internal_create_qp( | |||
461 | ib_device); | 461 | ib_device); |
462 | struct ib_ucontext *context = NULL; | 462 | struct ib_ucontext *context = NULL; |
463 | u64 h_ret; | 463 | u64 h_ret; |
464 | int is_llqp = 0, has_srq = 0; | 464 | int is_llqp = 0, has_srq = 0, is_user = 0; |
465 | int qp_type, max_send_sge, max_recv_sge, ret; | 465 | int qp_type, max_send_sge, max_recv_sge, ret; |
466 | 466 | ||
467 | /* h_call's out parameters */ | 467 | /* h_call's out parameters */ |
@@ -609,9 +609,6 @@ static struct ehca_qp *internal_create_qp( | |||
609 | } | 609 | } |
610 | } | 610 | } |
611 | 611 | ||
612 | if (pd->uobject && udata) | ||
613 | context = pd->uobject->context; | ||
614 | |||
615 | my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL); | 612 | my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL); |
616 | if (!my_qp) { | 613 | if (!my_qp) { |
617 | ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd); | 614 | ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd); |
@@ -619,6 +616,11 @@ static struct ehca_qp *internal_create_qp( | |||
619 | return ERR_PTR(-ENOMEM); | 616 | return ERR_PTR(-ENOMEM); |
620 | } | 617 | } |
621 | 618 | ||
619 | if (pd->uobject && udata) { | ||
620 | is_user = 1; | ||
621 | context = pd->uobject->context; | ||
622 | } | ||
623 | |||
622 | atomic_set(&my_qp->nr_events, 0); | 624 | atomic_set(&my_qp->nr_events, 0); |
623 | init_waitqueue_head(&my_qp->wait_completion); | 625 | init_waitqueue_head(&my_qp->wait_completion); |
624 | spin_lock_init(&my_qp->spinlock_s); | 626 | spin_lock_init(&my_qp->spinlock_s); |
@@ -707,7 +709,7 @@ static struct ehca_qp *internal_create_qp( | |||
707 | (parms.squeue.is_small || parms.rqueue.is_small); | 709 | (parms.squeue.is_small || parms.rqueue.is_small); |
708 | } | 710 | } |
709 | 711 | ||
710 | h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms); | 712 | h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms, is_user); |
711 | if (h_ret != H_SUCCESS) { | 713 | if (h_ret != H_SUCCESS) { |
712 | ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli", | 714 | ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli", |
713 | h_ret); | 715 | h_ret); |
@@ -769,18 +771,20 @@ static struct ehca_qp *internal_create_qp( | |||
769 | goto create_qp_exit2; | 771 | goto create_qp_exit2; |
770 | } | 772 | } |
771 | 773 | ||
772 | my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length / | 774 | if (!is_user) { |
773 | my_qp->ipz_squeue.qe_size; | 775 | my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length / |
774 | my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries * | 776 | my_qp->ipz_squeue.qe_size; |
775 | sizeof(struct ehca_qmap_entry)); | 777 | my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries * |
776 | if (!my_qp->sq_map.map) { | 778 | sizeof(struct ehca_qmap_entry)); |
777 | ehca_err(pd->device, "Couldn't allocate squeue " | 779 | if (!my_qp->sq_map.map) { |
778 | "map ret=%i", ret); | 780 | ehca_err(pd->device, "Couldn't allocate squeue " |
779 | goto create_qp_exit3; | 781 | "map ret=%i", ret); |
782 | goto create_qp_exit3; | ||
783 | } | ||
784 | INIT_LIST_HEAD(&my_qp->sq_err_node); | ||
785 | /* to avoid the generation of bogus flush CQEs */ | ||
786 | reset_queue_map(&my_qp->sq_map); | ||
780 | } | 787 | } |
781 | INIT_LIST_HEAD(&my_qp->sq_err_node); | ||
782 | /* to avoid the generation of bogus flush CQEs */ | ||
783 | reset_queue_map(&my_qp->sq_map); | ||
784 | } | 788 | } |
785 | 789 | ||
786 | if (HAS_RQ(my_qp)) { | 790 | if (HAS_RQ(my_qp)) { |
@@ -792,20 +796,21 @@ static struct ehca_qp *internal_create_qp( | |||
792 | "and pages ret=%i", ret); | 796 | "and pages ret=%i", ret); |
793 | goto create_qp_exit4; | 797 | goto create_qp_exit4; |
794 | } | 798 | } |
795 | 799 | if (!is_user) { | |
796 | my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length / | 800 | my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length / |
797 | my_qp->ipz_rqueue.qe_size; | 801 | my_qp->ipz_rqueue.qe_size; |
798 | my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries * | 802 | my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries * |
799 | sizeof(struct ehca_qmap_entry)); | 803 | sizeof(struct ehca_qmap_entry)); |
800 | if (!my_qp->rq_map.map) { | 804 | if (!my_qp->rq_map.map) { |
801 | ehca_err(pd->device, "Couldn't allocate squeue " | 805 | ehca_err(pd->device, "Couldn't allocate squeue " |
802 | "map ret=%i", ret); | 806 | "map ret=%i", ret); |
803 | goto create_qp_exit5; | 807 | goto create_qp_exit5; |
808 | } | ||
809 | INIT_LIST_HEAD(&my_qp->rq_err_node); | ||
810 | /* to avoid the generation of bogus flush CQEs */ | ||
811 | reset_queue_map(&my_qp->rq_map); | ||
804 | } | 812 | } |
805 | INIT_LIST_HEAD(&my_qp->rq_err_node); | 813 | } else if (init_attr->srq && !is_user) { |
806 | /* to avoid the generation of bogus flush CQEs */ | ||
807 | reset_queue_map(&my_qp->rq_map); | ||
808 | } else if (init_attr->srq) { | ||
809 | /* this is a base QP, use the queue map of the SRQ */ | 814 | /* this is a base QP, use the queue map of the SRQ */ |
810 | my_qp->rq_map = my_srq->rq_map; | 815 | my_qp->rq_map = my_srq->rq_map; |
811 | INIT_LIST_HEAD(&my_qp->rq_err_node); | 816 | INIT_LIST_HEAD(&my_qp->rq_err_node); |
@@ -918,7 +923,7 @@ create_qp_exit7: | |||
918 | kfree(my_qp->mod_qp_parm); | 923 | kfree(my_qp->mod_qp_parm); |
919 | 924 | ||
920 | create_qp_exit6: | 925 | create_qp_exit6: |
921 | if (HAS_RQ(my_qp)) | 926 | if (HAS_RQ(my_qp) && !is_user) |
922 | vfree(my_qp->rq_map.map); | 927 | vfree(my_qp->rq_map.map); |
923 | 928 | ||
924 | create_qp_exit5: | 929 | create_qp_exit5: |
@@ -926,7 +931,7 @@ create_qp_exit5: | |||
926 | ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); | 931 | ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); |
927 | 932 | ||
928 | create_qp_exit4: | 933 | create_qp_exit4: |
929 | if (HAS_SQ(my_qp)) | 934 | if (HAS_SQ(my_qp) && !is_user) |
930 | vfree(my_qp->sq_map.map); | 935 | vfree(my_qp->sq_map.map); |
931 | 936 | ||
932 | create_qp_exit3: | 937 | create_qp_exit3: |
@@ -1244,6 +1249,7 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
1244 | u64 update_mask; | 1249 | u64 update_mask; |
1245 | u64 h_ret; | 1250 | u64 h_ret; |
1246 | int bad_wqe_cnt = 0; | 1251 | int bad_wqe_cnt = 0; |
1252 | int is_user = 0; | ||
1247 | int squeue_locked = 0; | 1253 | int squeue_locked = 0; |
1248 | unsigned long flags = 0; | 1254 | unsigned long flags = 0; |
1249 | 1255 | ||
@@ -1266,6 +1272,8 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
1266 | ret = ehca2ib_return_code(h_ret); | 1272 | ret = ehca2ib_return_code(h_ret); |
1267 | goto modify_qp_exit1; | 1273 | goto modify_qp_exit1; |
1268 | } | 1274 | } |
1275 | if (ibqp->uobject) | ||
1276 | is_user = 1; | ||
1269 | 1277 | ||
1270 | qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state); | 1278 | qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state); |
1271 | 1279 | ||
@@ -1728,7 +1736,8 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
1728 | goto modify_qp_exit2; | 1736 | goto modify_qp_exit2; |
1729 | } | 1737 | } |
1730 | } | 1738 | } |
1731 | if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)) { | 1739 | if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR) |
1740 | && !is_user) { | ||
1732 | ret = check_for_left_cqes(my_qp, shca); | 1741 | ret = check_for_left_cqes(my_qp, shca); |
1733 | if (ret) | 1742 | if (ret) |
1734 | goto modify_qp_exit2; | 1743 | goto modify_qp_exit2; |
@@ -1738,16 +1747,17 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
1738 | ipz_qeit_reset(&my_qp->ipz_rqueue); | 1747 | ipz_qeit_reset(&my_qp->ipz_rqueue); |
1739 | ipz_qeit_reset(&my_qp->ipz_squeue); | 1748 | ipz_qeit_reset(&my_qp->ipz_squeue); |
1740 | 1749 | ||
1741 | if (qp_cur_state == IB_QPS_ERR) { | 1750 | if (qp_cur_state == IB_QPS_ERR && !is_user) { |
1742 | del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); | 1751 | del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); |
1743 | 1752 | ||
1744 | if (HAS_RQ(my_qp)) | 1753 | if (HAS_RQ(my_qp)) |
1745 | del_from_err_list(my_qp->recv_cq, | 1754 | del_from_err_list(my_qp->recv_cq, |
1746 | &my_qp->rq_err_node); | 1755 | &my_qp->rq_err_node); |
1747 | } | 1756 | } |
1748 | reset_queue_map(&my_qp->sq_map); | 1757 | if (!is_user) |
1758 | reset_queue_map(&my_qp->sq_map); | ||
1749 | 1759 | ||
1750 | if (HAS_RQ(my_qp)) | 1760 | if (HAS_RQ(my_qp) && !is_user) |
1751 | reset_queue_map(&my_qp->rq_map); | 1761 | reset_queue_map(&my_qp->rq_map); |
1752 | } | 1762 | } |
1753 | 1763 | ||
@@ -2138,10 +2148,12 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, | |||
2138 | int ret; | 2148 | int ret; |
2139 | u64 h_ret; | 2149 | u64 h_ret; |
2140 | u8 port_num; | 2150 | u8 port_num; |
2151 | int is_user = 0; | ||
2141 | enum ib_qp_type qp_type; | 2152 | enum ib_qp_type qp_type; |
2142 | unsigned long flags; | 2153 | unsigned long flags; |
2143 | 2154 | ||
2144 | if (uobject) { | 2155 | if (uobject) { |
2156 | is_user = 1; | ||
2145 | if (my_qp->mm_count_galpa || | 2157 | if (my_qp->mm_count_galpa || |
2146 | my_qp->mm_count_rqueue || my_qp->mm_count_squeue) { | 2158 | my_qp->mm_count_rqueue || my_qp->mm_count_squeue) { |
2147 | ehca_err(dev, "Resources still referenced in " | 2159 | ehca_err(dev, "Resources still referenced in " |
@@ -2168,10 +2180,10 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, | |||
2168 | * SRQs will never get into an error list and do not have a recv_cq, | 2180 | * SRQs will never get into an error list and do not have a recv_cq, |
2169 | * so we need to skip them here. | 2181 | * so we need to skip them here. |
2170 | */ | 2182 | */ |
2171 | if (HAS_RQ(my_qp) && !IS_SRQ(my_qp)) | 2183 | if (HAS_RQ(my_qp) && !IS_SRQ(my_qp) && !is_user) |
2172 | del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node); | 2184 | del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node); |
2173 | 2185 | ||
2174 | if (HAS_SQ(my_qp)) | 2186 | if (HAS_SQ(my_qp) && !is_user) |
2175 | del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); | 2187 | del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); |
2176 | 2188 | ||
2177 | /* now wait until all pending events have completed */ | 2189 | /* now wait until all pending events have completed */ |
@@ -2209,13 +2221,13 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, | |||
2209 | 2221 | ||
2210 | if (HAS_RQ(my_qp)) { | 2222 | if (HAS_RQ(my_qp)) { |
2211 | ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); | 2223 | ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); |
2212 | 2224 | if (!is_user) | |
2213 | vfree(my_qp->rq_map.map); | 2225 | vfree(my_qp->rq_map.map); |
2214 | } | 2226 | } |
2215 | if (HAS_SQ(my_qp)) { | 2227 | if (HAS_SQ(my_qp)) { |
2216 | ipz_queue_dtor(my_pd, &my_qp->ipz_squeue); | 2228 | ipz_queue_dtor(my_pd, &my_qp->ipz_squeue); |
2217 | 2229 | if (!is_user) | |
2218 | vfree(my_qp->sq_map.map); | 2230 | vfree(my_qp->sq_map.map); |
2219 | } | 2231 | } |
2220 | kmem_cache_free(qp_cache, my_qp); | 2232 | kmem_cache_free(qp_cache, my_qp); |
2221 | atomic_dec(&shca->num_qps); | 2233 | atomic_dec(&shca->num_qps); |
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c index d0ab0c0d5e91..4d5dc3304d42 100644 --- a/drivers/infiniband/hw/ehca/hcp_if.c +++ b/drivers/infiniband/hw/ehca/hcp_if.c | |||
@@ -284,7 +284,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, | |||
284 | param->act_pages = (u32)outs[4]; | 284 | param->act_pages = (u32)outs[4]; |
285 | 285 | ||
286 | if (ret == H_SUCCESS) | 286 | if (ret == H_SUCCESS) |
287 | hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]); | 287 | hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]); |
288 | 288 | ||
289 | if (ret == H_NOT_ENOUGH_RESOURCES) | 289 | if (ret == H_NOT_ENOUGH_RESOURCES) |
290 | ehca_gen_err("Not enough resources. ret=%lli", ret); | 290 | ehca_gen_err("Not enough resources. ret=%lli", ret); |
@@ -293,7 +293,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, | |||
293 | } | 293 | } |
294 | 294 | ||
295 | u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, | 295 | u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, |
296 | struct ehca_alloc_qp_parms *parms) | 296 | struct ehca_alloc_qp_parms *parms, int is_user) |
297 | { | 297 | { |
298 | u64 ret; | 298 | u64 ret; |
299 | u64 allocate_controls, max_r10_reg, r11, r12; | 299 | u64 allocate_controls, max_r10_reg, r11, r12; |
@@ -359,7 +359,7 @@ u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, | |||
359 | (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]); | 359 | (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]); |
360 | 360 | ||
361 | if (ret == H_SUCCESS) | 361 | if (ret == H_SUCCESS) |
362 | hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]); | 362 | hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]); |
363 | 363 | ||
364 | if (ret == H_NOT_ENOUGH_RESOURCES) | 364 | if (ret == H_NOT_ENOUGH_RESOURCES) |
365 | ehca_gen_err("Not enough resources. ret=%lli", ret); | 365 | ehca_gen_err("Not enough resources. ret=%lli", ret); |
diff --git a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h index 2c3c6e0ea5c2..39c1c3618ec7 100644 --- a/drivers/infiniband/hw/ehca/hcp_if.h +++ b/drivers/infiniband/hw/ehca/hcp_if.h | |||
@@ -78,7 +78,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, | |||
78 | * initialize resources, create empty QPPTs (2 rings). | 78 | * initialize resources, create empty QPPTs (2 rings). |
79 | */ | 79 | */ |
80 | u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, | 80 | u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, |
81 | struct ehca_alloc_qp_parms *parms); | 81 | struct ehca_alloc_qp_parms *parms, int is_user); |
82 | 82 | ||
83 | u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, | 83 | u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, |
84 | const u8 port_id, | 84 | const u8 port_id, |
diff --git a/drivers/infiniband/hw/ehca/hcp_phyp.c b/drivers/infiniband/hw/ehca/hcp_phyp.c index 214821095cb1..b3e0e72e8a73 100644 --- a/drivers/infiniband/hw/ehca/hcp_phyp.c +++ b/drivers/infiniband/hw/ehca/hcp_phyp.c | |||
@@ -54,12 +54,15 @@ int hcall_unmap_page(u64 mapaddr) | |||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | int hcp_galpas_ctor(struct h_galpas *galpas, | 57 | int hcp_galpas_ctor(struct h_galpas *galpas, int is_user, |
58 | u64 paddr_kernel, u64 paddr_user) | 58 | u64 paddr_kernel, u64 paddr_user) |
59 | { | 59 | { |
60 | int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle); | 60 | if (!is_user) { |
61 | if (ret) | 61 | int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle); |
62 | return ret; | 62 | if (ret) |
63 | return ret; | ||
64 | } else | ||
65 | galpas->kernel.fw_handle = 0; | ||
63 | 66 | ||
64 | galpas->user.fw_handle = paddr_user; | 67 | galpas->user.fw_handle = paddr_user; |
65 | 68 | ||
diff --git a/drivers/infiniband/hw/ehca/hcp_phyp.h b/drivers/infiniband/hw/ehca/hcp_phyp.h index 5305c2a3ed94..204227d5303a 100644 --- a/drivers/infiniband/hw/ehca/hcp_phyp.h +++ b/drivers/infiniband/hw/ehca/hcp_phyp.h | |||
@@ -78,7 +78,7 @@ static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value) | |||
78 | *(volatile u64 __force *)addr = value; | 78 | *(volatile u64 __force *)addr = value; |
79 | } | 79 | } |
80 | 80 | ||
81 | int hcp_galpas_ctor(struct h_galpas *galpas, | 81 | int hcp_galpas_ctor(struct h_galpas *galpas, int is_user, |
82 | u64 paddr_kernel, u64 paddr_user); | 82 | u64 paddr_kernel, u64 paddr_user); |
83 | 83 | ||
84 | int hcp_galpas_dtor(struct h_galpas *galpas); | 84 | int hcp_galpas_dtor(struct h_galpas *galpas); |