#include "qp.h"
 #include "vt.h"
 
-static void get_map_page(struct rvt_qpn_table *qpt, struct rvt_qpn_map *map)
+static void get_map_page(struct rvt_qpn_table *qpt,
+                        struct rvt_qpn_map *map,
+                        gfp_t gfp)
 {
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       unsigned long page = get_zeroed_page(gfp);
 
        /*
         * Free the page if someone raced with us installing it.
                    rdi->dparms.qpn_res_start, rdi->dparms.qpn_res_end);
        for (i = rdi->dparms.qpn_res_start; i <= rdi->dparms.qpn_res_end; i++) {
                if (!map->page) {
-                       get_map_page(qpt, map);
+                       get_map_page(qpt, map, GFP_KERNEL);
                        if (!map->page) {
                                ret = -ENOMEM;
                                break;
  * zero/one for QP type IB_QPT_SMI/IB_QPT_GSI.
  */
 static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt,
-                    enum ib_qp_type type, u8 port)
+                    enum ib_qp_type type, u8 port, gfp_t gfp)
 {
        u32 i, offset, max_scan, qpn;
        struct rvt_qpn_map *map;
        u32 ret;
 
        if (rdi->driver_f.alloc_qpn)
-               return rdi->driver_f.alloc_qpn(rdi, qpt, type, port);
+               return rdi->driver_f.alloc_qpn(rdi, qpt, type, port,
+                                              GFP_KERNEL);
 
        if (type == IB_QPT_SMI || type == IB_QPT_GSI) {
                unsigned n;
        max_scan = qpt->nmaps - !offset;
        for (i = 0;;) {
                if (unlikely(!map->page)) {
-                       get_map_page(qpt, map);
+                       get_map_page(qpt, map, gfp);
                        if (unlikely(!map->page))
                                break;
                }
        struct ib_qp *ret = ERR_PTR(-ENOMEM);
        struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device);
        void *priv = NULL;
+       gfp_t gfp;
 
        if (!rdi)
                return ERR_PTR(-EINVAL);
 
        if (init_attr->cap.max_send_sge > rdi->dparms.props.max_sge ||
            init_attr->cap.max_send_wr > rdi->dparms.props.max_qp_wr ||
-           init_attr->create_flags)
+           init_attr->create_flags & ~(IB_QP_CREATE_USE_GFP_NOIO))
                return ERR_PTR(-EINVAL);
 
+       /* GFP_NOIO is applicable to RC QP's only */
+
+       if (init_attr->create_flags & IB_QP_CREATE_USE_GFP_NOIO &&
+           init_attr->qp_type != IB_QPT_RC)
+               return ERR_PTR(-EINVAL);
+
+       gfp = init_attr->create_flags & IB_QP_CREATE_USE_GFP_NOIO ?
+                                               GFP_NOIO : GFP_KERNEL;
+
        /* Check receive queue parameters if no SRQ is specified. */
        if (!init_attr->srq) {
                if (init_attr->cap.max_recv_sge > rdi->dparms.props.max_sge ||
                sz = sizeof(struct rvt_sge) *
                        init_attr->cap.max_send_sge +
                        sizeof(struct rvt_swqe);
-               swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz);
+               if (gfp == GFP_NOIO)
+                       swq = __vmalloc(
+                               (init_attr->cap.max_send_wr + 1) * sz,
+                               gfp, PAGE_KERNEL);
+               else
+                       swq = vmalloc(
+                               (init_attr->cap.max_send_wr + 1) * sz);
                if (!swq)
                        return ERR_PTR(-ENOMEM);
 
                } else if (init_attr->cap.max_recv_sge > 1)
                        sg_list_sz = sizeof(*qp->r_sg_list) *
                                (init_attr->cap.max_recv_sge - 1);
-               qp = kzalloc(sz + sg_list_sz, GFP_KERNEL);
+               qp = kzalloc(sz + sg_list_sz, gfp);
                if (!qp)
                        goto bail_swq;
 
                 * Driver needs to set up it's private QP structure and do any
                 * initialization that is needed.
                 */
-               priv = rdi->driver_f.qp_priv_alloc(rdi, qp);
+               priv = rdi->driver_f.qp_priv_alloc(rdi, qp, gfp);
                if (!priv)
                        goto bail_qp;
                qp->priv = priv;
                        qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
                        sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) +
                                sizeof(struct rvt_rwqe);
-                       qp->r_rq.wq = vmalloc_user(sizeof(struct rvt_rwq) +
-                                                  qp->r_rq.size * sz);
+                       if (udata)
+                               qp->r_rq.wq = vmalloc_user(
+                                               sizeof(struct rvt_rwq) +
+                                               qp->r_rq.size * sz);
+                       else if (gfp == GFP_NOIO)
+                               qp->r_rq.wq = __vmalloc(
+                                               sizeof(struct rvt_rwq) +
+                                               qp->r_rq.size * sz,
+                                               gfp, PAGE_KERNEL);
+                       else
+                               qp->r_rq.wq = vmalloc(
+                                               sizeof(struct rvt_rwq) +
+                                               qp->r_rq.size * sz);
                        if (!qp->r_rq.wq)
                                goto bail_driver_priv;
                }
 
                err = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
                                init_attr->qp_type,
-                               init_attr->port_num);
+                               init_attr->port_num, gfp);
                if (err < 0) {
                        ret = ERR_PTR(err);
                        goto bail_rq_wq;
 
        const char * (*get_card_name)(struct rvt_dev_info *rdi);
        struct pci_dev * (*get_pci_dev)(struct rvt_dev_info *rdi);
        unsigned (*free_all_qps)(struct rvt_dev_info *rdi);
-       void * (*qp_priv_alloc)(struct rvt_dev_info *rdi, struct rvt_qp *qp);
+       void * (*qp_priv_alloc)(struct rvt_dev_info *rdi, struct rvt_qp *qp,
+                               gfp_t gfp);
        void (*qp_priv_free)(struct rvt_dev_info *rdi, struct rvt_qp *qp);
        void (*notify_qp_reset)(struct rvt_qp *qp);
 
        void (*notify_new_ah)(struct ib_device *, struct ib_ah_attr *,
                              struct rvt_ah *);
        int (*alloc_qpn)(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt,
-                        enum ib_qp_type type, u8 port);
+                        enum ib_qp_type type, u8 port, gfp_t gfp);
 };
 
 struct rvt_dev_info {