diff options
-rw-r--r-- | drivers/infiniband/sw/rdmavt/qp.c | 56 | ||||
-rw-r--r-- | include/rdma/rdma_vt.h | 5 |
2 files changed, 46 insertions, 15 deletions
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index ee19eae38d0b..43346a773ff3 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c | |||
@@ -53,9 +53,11 @@ | |||
53 | #include "qp.h" | 53 | #include "qp.h" |
54 | #include "vt.h" | 54 | #include "vt.h" |
55 | 55 | ||
56 | static void get_map_page(struct rvt_qpn_table *qpt, struct rvt_qpn_map *map) | 56 | static void get_map_page(struct rvt_qpn_table *qpt, |
57 | struct rvt_qpn_map *map, | ||
58 | gfp_t gfp) | ||
57 | { | 59 | { |
58 | unsigned long page = get_zeroed_page(GFP_KERNEL); | 60 | unsigned long page = get_zeroed_page(gfp); |
59 | 61 | ||
60 | /* | 62 | /* |
61 | * Free the page if someone raced with us installing it. | 63 | * Free the page if someone raced with us installing it. |
@@ -107,7 +109,7 @@ static int init_qpn_table(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt) | |||
107 | rdi->dparms.qpn_res_start, rdi->dparms.qpn_res_end); | 109 | rdi->dparms.qpn_res_start, rdi->dparms.qpn_res_end); |
108 | for (i = rdi->dparms.qpn_res_start; i <= rdi->dparms.qpn_res_end; i++) { | 110 | for (i = rdi->dparms.qpn_res_start; i <= rdi->dparms.qpn_res_end; i++) { |
109 | if (!map->page) { | 111 | if (!map->page) { |
110 | get_map_page(qpt, map); | 112 | get_map_page(qpt, map, GFP_KERNEL); |
111 | if (!map->page) { | 113 | if (!map->page) { |
112 | ret = -ENOMEM; | 114 | ret = -ENOMEM; |
113 | break; | 115 | break; |
@@ -263,14 +265,15 @@ static inline unsigned mk_qpn(struct rvt_qpn_table *qpt, | |||
263 | * zero/one for QP type IB_QPT_SMI/IB_QPT_GSI. | 265 | * zero/one for QP type IB_QPT_SMI/IB_QPT_GSI. |
264 | */ | 266 | */ |
265 | static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt, | 267 | static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt, |
266 | enum ib_qp_type type, u8 port) | 268 | enum ib_qp_type type, u8 port, gfp_t gfp) |
267 | { | 269 | { |
268 | u32 i, offset, max_scan, qpn; | 270 | u32 i, offset, max_scan, qpn; |
269 | struct rvt_qpn_map *map; | 271 | struct rvt_qpn_map *map; |
270 | u32 ret; | 272 | u32 ret; |
271 | 273 | ||
272 | if (rdi->driver_f.alloc_qpn) | 274 | if (rdi->driver_f.alloc_qpn) |
273 | return rdi->driver_f.alloc_qpn(rdi, qpt, type, port); | 275 | return rdi->driver_f.alloc_qpn(rdi, qpt, type, port, |
276 | GFP_KERNEL); | ||
274 | 277 | ||
275 | if (type == IB_QPT_SMI || type == IB_QPT_GSI) { | 278 | if (type == IB_QPT_SMI || type == IB_QPT_GSI) { |
276 | unsigned n; | 279 | unsigned n; |
@@ -295,7 +298,7 @@ static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt, | |||
295 | max_scan = qpt->nmaps - !offset; | 298 | max_scan = qpt->nmaps - !offset; |
296 | for (i = 0;;) { | 299 | for (i = 0;;) { |
297 | if (unlikely(!map->page)) { | 300 | if (unlikely(!map->page)) { |
298 | get_map_page(qpt, map); | 301 | get_map_page(qpt, map, gfp); |
299 | if (unlikely(!map->page)) | 302 | if (unlikely(!map->page)) |
300 | break; | 303 | break; |
301 | } | 304 | } |
@@ -437,15 +440,25 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, | |||
437 | struct ib_qp *ret = ERR_PTR(-ENOMEM); | 440 | struct ib_qp *ret = ERR_PTR(-ENOMEM); |
438 | struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device); | 441 | struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device); |
439 | void *priv = NULL; | 442 | void *priv = NULL; |
443 | gfp_t gfp; | ||
440 | 444 | ||
441 | if (!rdi) | 445 | if (!rdi) |
442 | return ERR_PTR(-EINVAL); | 446 | return ERR_PTR(-EINVAL); |
443 | 447 | ||
444 | if (init_attr->cap.max_send_sge > rdi->dparms.props.max_sge || | 448 | if (init_attr->cap.max_send_sge > rdi->dparms.props.max_sge || |
445 | init_attr->cap.max_send_wr > rdi->dparms.props.max_qp_wr || | 449 | init_attr->cap.max_send_wr > rdi->dparms.props.max_qp_wr || |
446 | init_attr->create_flags) | 450 | init_attr->create_flags & ~(IB_QP_CREATE_USE_GFP_NOIO)) |
447 | return ERR_PTR(-EINVAL); | 451 | return ERR_PTR(-EINVAL); |
448 | 452 | ||
453 | /* GFP_NOIO is applicable to RC QP's only */ | ||
454 | |||
455 | if (init_attr->create_flags & IB_QP_CREATE_USE_GFP_NOIO && | ||
456 | init_attr->qp_type != IB_QPT_RC) | ||
457 | return ERR_PTR(-EINVAL); | ||
458 | |||
459 | gfp = init_attr->create_flags & IB_QP_CREATE_USE_GFP_NOIO ? | ||
460 | GFP_NOIO : GFP_KERNEL; | ||
461 | |||
449 | /* Check receive queue parameters if no SRQ is specified. */ | 462 | /* Check receive queue parameters if no SRQ is specified. */ |
450 | if (!init_attr->srq) { | 463 | if (!init_attr->srq) { |
451 | if (init_attr->cap.max_recv_sge > rdi->dparms.props.max_sge || | 464 | if (init_attr->cap.max_recv_sge > rdi->dparms.props.max_sge || |
@@ -471,7 +484,13 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, | |||
471 | sz = sizeof(struct rvt_sge) * | 484 | sz = sizeof(struct rvt_sge) * |
472 | init_attr->cap.max_send_sge + | 485 | init_attr->cap.max_send_sge + |
473 | sizeof(struct rvt_swqe); | 486 | sizeof(struct rvt_swqe); |
474 | swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz); | 487 | if (gfp == GFP_NOIO) |
488 | swq = __vmalloc( | ||
489 | (init_attr->cap.max_send_wr + 1) * sz, | ||
490 | gfp, PAGE_KERNEL); | ||
491 | else | ||
492 | swq = vmalloc( | ||
493 | (init_attr->cap.max_send_wr + 1) * sz); | ||
475 | if (!swq) | 494 | if (!swq) |
476 | return ERR_PTR(-ENOMEM); | 495 | return ERR_PTR(-ENOMEM); |
477 | 496 | ||
@@ -486,7 +505,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, | |||
486 | } else if (init_attr->cap.max_recv_sge > 1) | 505 | } else if (init_attr->cap.max_recv_sge > 1) |
487 | sg_list_sz = sizeof(*qp->r_sg_list) * | 506 | sg_list_sz = sizeof(*qp->r_sg_list) * |
488 | (init_attr->cap.max_recv_sge - 1); | 507 | (init_attr->cap.max_recv_sge - 1); |
489 | qp = kzalloc(sz + sg_list_sz, GFP_KERNEL); | 508 | qp = kzalloc(sz + sg_list_sz, gfp); |
490 | if (!qp) | 509 | if (!qp) |
491 | goto bail_swq; | 510 | goto bail_swq; |
492 | 511 | ||
@@ -496,7 +515,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, | |||
496 | * Driver needs to set up it's private QP structure and do any | 515 | * Driver needs to set up it's private QP structure and do any |
497 | * initialization that is needed. | 516 | * initialization that is needed. |
498 | */ | 517 | */ |
499 | priv = rdi->driver_f.qp_priv_alloc(rdi, qp); | 518 | priv = rdi->driver_f.qp_priv_alloc(rdi, qp, gfp); |
500 | if (!priv) | 519 | if (!priv) |
501 | goto bail_qp; | 520 | goto bail_qp; |
502 | qp->priv = priv; | 521 | qp->priv = priv; |
@@ -510,8 +529,19 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, | |||
510 | qp->r_rq.max_sge = init_attr->cap.max_recv_sge; | 529 | qp->r_rq.max_sge = init_attr->cap.max_recv_sge; |
511 | sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) + | 530 | sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) + |
512 | sizeof(struct rvt_rwqe); | 531 | sizeof(struct rvt_rwqe); |
513 | qp->r_rq.wq = vmalloc_user(sizeof(struct rvt_rwq) + | 532 | if (udata) |
514 | qp->r_rq.size * sz); | 533 | qp->r_rq.wq = vmalloc_user( |
534 | sizeof(struct rvt_rwq) + | ||
535 | qp->r_rq.size * sz); | ||
536 | else if (gfp == GFP_NOIO) | ||
537 | qp->r_rq.wq = __vmalloc( | ||
538 | sizeof(struct rvt_rwq) + | ||
539 | qp->r_rq.size * sz, | ||
540 | gfp, PAGE_KERNEL); | ||
541 | else | ||
542 | qp->r_rq.wq = vmalloc( | ||
543 | sizeof(struct rvt_rwq) + | ||
544 | qp->r_rq.size * sz); | ||
515 | if (!qp->r_rq.wq) | 545 | if (!qp->r_rq.wq) |
516 | goto bail_driver_priv; | 546 | goto bail_driver_priv; |
517 | } | 547 | } |
@@ -537,7 +567,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, | |||
537 | 567 | ||
538 | err = alloc_qpn(rdi, &rdi->qp_dev->qpn_table, | 568 | err = alloc_qpn(rdi, &rdi->qp_dev->qpn_table, |
539 | init_attr->qp_type, | 569 | init_attr->qp_type, |
540 | init_attr->port_num); | 570 | init_attr->port_num, gfp); |
541 | if (err < 0) { | 571 | if (err < 0) { |
542 | ret = ERR_PTR(err); | 572 | ret = ERR_PTR(err); |
543 | goto bail_rq_wq; | 573 | goto bail_rq_wq; |
diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h index 725778a6781d..70a9596b859d 100644 --- a/include/rdma/rdma_vt.h +++ b/include/rdma/rdma_vt.h | |||
@@ -223,7 +223,8 @@ struct rvt_driver_provided { | |||
223 | const char * (*get_card_name)(struct rvt_dev_info *rdi); | 223 | const char * (*get_card_name)(struct rvt_dev_info *rdi); |
224 | struct pci_dev * (*get_pci_dev)(struct rvt_dev_info *rdi); | 224 | struct pci_dev * (*get_pci_dev)(struct rvt_dev_info *rdi); |
225 | unsigned (*free_all_qps)(struct rvt_dev_info *rdi); | 225 | unsigned (*free_all_qps)(struct rvt_dev_info *rdi); |
226 | void * (*qp_priv_alloc)(struct rvt_dev_info *rdi, struct rvt_qp *qp); | 226 | void * (*qp_priv_alloc)(struct rvt_dev_info *rdi, struct rvt_qp *qp, |
227 | gfp_t gfp); | ||
227 | void (*qp_priv_free)(struct rvt_dev_info *rdi, struct rvt_qp *qp); | 228 | void (*qp_priv_free)(struct rvt_dev_info *rdi, struct rvt_qp *qp); |
228 | void (*notify_qp_reset)(struct rvt_qp *qp); | 229 | void (*notify_qp_reset)(struct rvt_qp *qp); |
229 | 230 | ||
@@ -234,7 +235,7 @@ struct rvt_driver_provided { | |||
234 | void (*notify_new_ah)(struct ib_device *, struct ib_ah_attr *, | 235 | void (*notify_new_ah)(struct ib_device *, struct ib_ah_attr *, |
235 | struct rvt_ah *); | 236 | struct rvt_ah *); |
236 | int (*alloc_qpn)(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt, | 237 | int (*alloc_qpn)(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt, |
237 | enum ib_qp_type type, u8 port); | 238 | enum ib_qp_type type, u8 port, gfp_t gfp); |
238 | }; | 239 | }; |
239 | 240 | ||
240 | struct rvt_dev_info { | 241 | struct rvt_dev_info { |