IB/ehca: Remove unnecessary memory operations for userspace queue pairs
The queue map for flush completion circumvention is only used for kernel space queue pairs. This patch skips the allocation of the queue maps in case the QP is created for userspace. In addition, this patch does not iomap the galpas for kernel usage if the queue pair is only used in userspace. These changes will improve the performance of creation of userspace queue pairs. Signed-off-by: Stefan Roscher <stefan.roscher@de.ibm.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
parent
c94f156f63
commit
1988d1fa1a
|
@ -461,7 +461,7 @@ static struct ehca_qp *internal_create_qp(
|
|||
ib_device);
|
||||
struct ib_ucontext *context = NULL;
|
||||
u64 h_ret;
|
||||
int is_llqp = 0, has_srq = 0;
|
||||
int is_llqp = 0, has_srq = 0, is_user = 0;
|
||||
int qp_type, max_send_sge, max_recv_sge, ret;
|
||||
|
||||
/* h_call's out parameters */
|
||||
|
@ -609,9 +609,6 @@ static struct ehca_qp *internal_create_qp(
|
|||
}
|
||||
}
|
||||
|
||||
if (pd->uobject && udata)
|
||||
context = pd->uobject->context;
|
||||
|
||||
my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
|
||||
if (!my_qp) {
|
||||
ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
|
||||
|
@ -619,6 +616,11 @@ static struct ehca_qp *internal_create_qp(
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (pd->uobject && udata) {
|
||||
is_user = 1;
|
||||
context = pd->uobject->context;
|
||||
}
|
||||
|
||||
atomic_set(&my_qp->nr_events, 0);
|
||||
init_waitqueue_head(&my_qp->wait_completion);
|
||||
spin_lock_init(&my_qp->spinlock_s);
|
||||
|
@ -707,7 +709,7 @@ static struct ehca_qp *internal_create_qp(
|
|||
(parms.squeue.is_small || parms.rqueue.is_small);
|
||||
}
|
||||
|
||||
h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);
|
||||
h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms, is_user);
|
||||
if (h_ret != H_SUCCESS) {
|
||||
ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli",
|
||||
h_ret);
|
||||
|
@ -769,18 +771,20 @@ static struct ehca_qp *internal_create_qp(
|
|||
goto create_qp_exit2;
|
||||
}
|
||||
|
||||
my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
|
||||
my_qp->ipz_squeue.qe_size;
|
||||
my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
|
||||
sizeof(struct ehca_qmap_entry));
|
||||
if (!my_qp->sq_map.map) {
|
||||
ehca_err(pd->device, "Couldn't allocate squeue "
|
||||
"map ret=%i", ret);
|
||||
goto create_qp_exit3;
|
||||
if (!is_user) {
|
||||
my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
|
||||
my_qp->ipz_squeue.qe_size;
|
||||
my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
|
||||
sizeof(struct ehca_qmap_entry));
|
||||
if (!my_qp->sq_map.map) {
|
||||
ehca_err(pd->device, "Couldn't allocate squeue "
|
||||
"map ret=%i", ret);
|
||||
goto create_qp_exit3;
|
||||
}
|
||||
INIT_LIST_HEAD(&my_qp->sq_err_node);
|
||||
/* to avoid the generation of bogus flush CQEs */
|
||||
reset_queue_map(&my_qp->sq_map);
|
||||
}
|
||||
INIT_LIST_HEAD(&my_qp->sq_err_node);
|
||||
/* to avoid the generation of bogus flush CQEs */
|
||||
reset_queue_map(&my_qp->sq_map);
|
||||
}
|
||||
|
||||
if (HAS_RQ(my_qp)) {
|
||||
|
@ -792,20 +796,21 @@ static struct ehca_qp *internal_create_qp(
|
|||
"and pages ret=%i", ret);
|
||||
goto create_qp_exit4;
|
||||
}
|
||||
|
||||
my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
|
||||
my_qp->ipz_rqueue.qe_size;
|
||||
my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
|
||||
sizeof(struct ehca_qmap_entry));
|
||||
if (!my_qp->rq_map.map) {
|
||||
ehca_err(pd->device, "Couldn't allocate squeue "
|
||||
"map ret=%i", ret);
|
||||
goto create_qp_exit5;
|
||||
if (!is_user) {
|
||||
my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
|
||||
my_qp->ipz_rqueue.qe_size;
|
||||
my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
|
||||
sizeof(struct ehca_qmap_entry));
|
||||
if (!my_qp->rq_map.map) {
|
||||
ehca_err(pd->device, "Couldn't allocate squeue "
|
||||
"map ret=%i", ret);
|
||||
goto create_qp_exit5;
|
||||
}
|
||||
INIT_LIST_HEAD(&my_qp->rq_err_node);
|
||||
/* to avoid the generation of bogus flush CQEs */
|
||||
reset_queue_map(&my_qp->rq_map);
|
||||
}
|
||||
INIT_LIST_HEAD(&my_qp->rq_err_node);
|
||||
/* to avoid the generation of bogus flush CQEs */
|
||||
reset_queue_map(&my_qp->rq_map);
|
||||
} else if (init_attr->srq) {
|
||||
} else if (init_attr->srq && !is_user) {
|
||||
/* this is a base QP, use the queue map of the SRQ */
|
||||
my_qp->rq_map = my_srq->rq_map;
|
||||
INIT_LIST_HEAD(&my_qp->rq_err_node);
|
||||
|
@ -918,7 +923,7 @@ create_qp_exit7:
|
|||
kfree(my_qp->mod_qp_parm);
|
||||
|
||||
create_qp_exit6:
|
||||
if (HAS_RQ(my_qp))
|
||||
if (HAS_RQ(my_qp) && !is_user)
|
||||
vfree(my_qp->rq_map.map);
|
||||
|
||||
create_qp_exit5:
|
||||
|
@ -926,7 +931,7 @@ create_qp_exit5:
|
|||
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
|
||||
|
||||
create_qp_exit4:
|
||||
if (HAS_SQ(my_qp))
|
||||
if (HAS_SQ(my_qp) && !is_user)
|
||||
vfree(my_qp->sq_map.map);
|
||||
|
||||
create_qp_exit3:
|
||||
|
@ -1244,6 +1249,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
|
|||
u64 update_mask;
|
||||
u64 h_ret;
|
||||
int bad_wqe_cnt = 0;
|
||||
int is_user = 0;
|
||||
int squeue_locked = 0;
|
||||
unsigned long flags = 0;
|
||||
|
||||
|
@ -1266,6 +1272,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
|
|||
ret = ehca2ib_return_code(h_ret);
|
||||
goto modify_qp_exit1;
|
||||
}
|
||||
if (ibqp->uobject)
|
||||
is_user = 1;
|
||||
|
||||
qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state);
|
||||
|
||||
|
@ -1728,7 +1736,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
|
|||
goto modify_qp_exit2;
|
||||
}
|
||||
}
|
||||
if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)) {
|
||||
if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)
|
||||
&& !is_user) {
|
||||
ret = check_for_left_cqes(my_qp, shca);
|
||||
if (ret)
|
||||
goto modify_qp_exit2;
|
||||
|
@ -1738,16 +1747,17 @@ static int internal_modify_qp(struct ib_qp *ibqp,
|
|||
ipz_qeit_reset(&my_qp->ipz_rqueue);
|
||||
ipz_qeit_reset(&my_qp->ipz_squeue);
|
||||
|
||||
if (qp_cur_state == IB_QPS_ERR) {
|
||||
if (qp_cur_state == IB_QPS_ERR && !is_user) {
|
||||
del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
|
||||
|
||||
if (HAS_RQ(my_qp))
|
||||
del_from_err_list(my_qp->recv_cq,
|
||||
&my_qp->rq_err_node);
|
||||
}
|
||||
reset_queue_map(&my_qp->sq_map);
|
||||
if (!is_user)
|
||||
reset_queue_map(&my_qp->sq_map);
|
||||
|
||||
if (HAS_RQ(my_qp))
|
||||
if (HAS_RQ(my_qp) && !is_user)
|
||||
reset_queue_map(&my_qp->rq_map);
|
||||
}
|
||||
|
||||
|
@ -2138,10 +2148,12 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
|
|||
int ret;
|
||||
u64 h_ret;
|
||||
u8 port_num;
|
||||
int is_user = 0;
|
||||
enum ib_qp_type qp_type;
|
||||
unsigned long flags;
|
||||
|
||||
if (uobject) {
|
||||
is_user = 1;
|
||||
if (my_qp->mm_count_galpa ||
|
||||
my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
|
||||
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,
|
|||
* SRQs will never get into an error list and do not have a recv_cq,
|
||||
* so we need to skip them here.
|
||||
*/
|
||||
if (HAS_RQ(my_qp) && !IS_SRQ(my_qp))
|
||||
if (HAS_RQ(my_qp) && !IS_SRQ(my_qp) && !is_user)
|
||||
del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node);
|
||||
|
||||
if (HAS_SQ(my_qp))
|
||||
if (HAS_SQ(my_qp) && !is_user)
|
||||
del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
|
||||
|
||||
/* 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,
|
|||
|
||||
if (HAS_RQ(my_qp)) {
|
||||
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
|
||||
|
||||
vfree(my_qp->rq_map.map);
|
||||
if (!is_user)
|
||||
vfree(my_qp->rq_map.map);
|
||||
}
|
||||
if (HAS_SQ(my_qp)) {
|
||||
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
|
||||
|
||||
vfree(my_qp->sq_map.map);
|
||||
if (!is_user)
|
||||
vfree(my_qp->sq_map.map);
|
||||
}
|
||||
kmem_cache_free(qp_cache, my_qp);
|
||||
atomic_dec(&shca->num_qps);
|
||||
|
|
|
@ -284,7 +284,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
|
|||
param->act_pages = (u32)outs[4];
|
||||
|
||||
if (ret == H_SUCCESS)
|
||||
hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
|
||||
hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);
|
||||
|
||||
if (ret == H_NOT_ENOUGH_RESOURCES)
|
||||
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,
|
|||
}
|
||||
|
||||
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
|
||||
struct ehca_alloc_qp_parms *parms)
|
||||
struct ehca_alloc_qp_parms *parms, int is_user)
|
||||
{
|
||||
u64 ret;
|
||||
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,
|
|||
(u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
|
||||
|
||||
if (ret == H_SUCCESS)
|
||||
hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
|
||||
hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);
|
||||
|
||||
if (ret == H_NOT_ENOUGH_RESOURCES)
|
||||
ehca_gen_err("Not enough resources. ret=%lli", ret);
|
||||
|
|
|
@ -78,7 +78,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
|
|||
* initialize resources, create empty QPPTs (2 rings).
|
||||
*/
|
||||
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
|
||||
struct ehca_alloc_qp_parms *parms);
|
||||
struct ehca_alloc_qp_parms *parms, int is_user);
|
||||
|
||||
u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
|
||||
const u8 port_id,
|
||||
|
|
|
@ -54,12 +54,15 @@ int hcall_unmap_page(u64 mapaddr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int hcp_galpas_ctor(struct h_galpas *galpas,
|
||||
int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
|
||||
u64 paddr_kernel, u64 paddr_user)
|
||||
{
|
||||
int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!is_user) {
|
||||
int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else
|
||||
galpas->kernel.fw_handle = 0;
|
||||
|
||||
galpas->user.fw_handle = paddr_user;
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value)
|
|||
*(volatile u64 __force *)addr = value;
|
||||
}
|
||||
|
||||
int hcp_galpas_ctor(struct h_galpas *galpas,
|
||||
int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
|
||||
u64 paddr_kernel, u64 paddr_user);
|
||||
|
||||
int hcp_galpas_dtor(struct h_galpas *galpas);
|
||||
|
|
Loading…
Reference in New Issue