···754754 struct ib_qp *qp;755755 int ret;756756757757+ if (qp_init_attr->rwq_ind_tbl &&758758+ (qp_init_attr->recv_cq ||759759+ qp_init_attr->srq || qp_init_attr->cap.max_recv_wr ||760760+ qp_init_attr->cap.max_recv_sge))761761+ return ERR_PTR(-EINVAL);762762+757763 /*758764 * If the callers is using the RDMA API calculate the resources759765 * needed for the RDMA READ/WRITE operations.···777771 qp->real_qp = qp;778772 qp->uobject = NULL;779773 qp->qp_type = qp_init_attr->qp_type;774774+ qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl;780775781776 atomic_set(&qp->usecnt, 0);782777 qp->mrs_used = 0;···795788 qp->srq = NULL;796789 } else {797790 qp->recv_cq = qp_init_attr->recv_cq;798798- atomic_inc(&qp_init_attr->recv_cq->usecnt);791791+ if (qp_init_attr->recv_cq)792792+ atomic_inc(&qp_init_attr->recv_cq->usecnt);799793 qp->srq = qp_init_attr->srq;800794 if (qp->srq)801795 atomic_inc(&qp_init_attr->srq->usecnt);···807799 qp->xrcd = NULL;808800809801 atomic_inc(&pd->usecnt);810810- atomic_inc(&qp_init_attr->send_cq->usecnt);802802+ if (qp_init_attr->send_cq)803803+ atomic_inc(&qp_init_attr->send_cq->usecnt);804804+ if (qp_init_attr->rwq_ind_tbl)805805+ atomic_inc(&qp->rwq_ind_tbl->usecnt);811806812807 if (qp_init_attr->cap.max_rdma_ctxs) {813808 ret = rdma_rw_init_mrs(qp, qp_init_attr);···12901279 struct ib_pd *pd;12911280 struct ib_cq *scq, *rcq;12921281 struct ib_srq *srq;12821282+ struct ib_rwq_ind_table *ind_tbl;12931283 int ret;1294128412951285 WARN_ON_ONCE(qp->mrs_used > 0);···13051293 scq = qp->send_cq;13061294 rcq = qp->recv_cq;13071295 srq = qp->srq;12961296+ ind_tbl = qp->rwq_ind_tbl;1308129713091298 if (!qp->uobject)13101299 rdma_rw_cleanup_mrs(qp);···13201307 atomic_dec(&rcq->usecnt);13211308 if (srq)13221309 atomic_dec(&srq->usecnt);13101310+ if (ind_tbl)13111311+ atomic_dec(&ind_tbl->usecnt);13231312 }1324131313251314 return ret;···15681553 return xrcd->device->dealloc_xrcd(xrcd);15691554}15701555EXPORT_SYMBOL(ib_dealloc_xrcd);15561556+15571557+/**15581558+ * ib_create_wq - Creates a WQ associated with the specified protection15591559+ * domain.15601560+ * @pd: The protection domain associated with the WQ.15611561+ * @wq_init_attr: A list of initial attributes required to create the15621562+ * WQ. If WQ creation succeeds, then the attributes are updated to15631563+ * the actual capabilities of the created WQ.15641564+ *15651565+ * wq_init_attr->max_wr and wq_init_attr->max_sge determine15661566+ * the requested size of the WQ, and set to the actual values allocated15671567+ * on return.15681568+ * If ib_create_wq() succeeds, then max_wr and max_sge will always be15691569+ * at least as large as the requested values.15701570+ */15711571+struct ib_wq *ib_create_wq(struct ib_pd *pd,15721572+ struct ib_wq_init_attr *wq_attr)15731573+{15741574+ struct ib_wq *wq;15751575+15761576+ if (!pd->device->create_wq)15771577+ return ERR_PTR(-ENOSYS);15781578+15791579+ wq = pd->device->create_wq(pd, wq_attr, NULL);15801580+ if (!IS_ERR(wq)) {15811581+ wq->event_handler = wq_attr->event_handler;15821582+ wq->wq_context = wq_attr->wq_context;15831583+ wq->wq_type = wq_attr->wq_type;15841584+ wq->cq = wq_attr->cq;15851585+ wq->device = pd->device;15861586+ wq->pd = pd;15871587+ wq->uobject = NULL;15881588+ atomic_inc(&pd->usecnt);15891589+ atomic_inc(&wq_attr->cq->usecnt);15901590+ atomic_set(&wq->usecnt, 0);15911591+ }15921592+ return wq;15931593+}15941594+EXPORT_SYMBOL(ib_create_wq);15951595+15961596+/**15971597+ * ib_destroy_wq - Destroys the specified WQ.15981598+ * @wq: The WQ to destroy.15991599+ */16001600+int ib_destroy_wq(struct ib_wq *wq)16011601+{16021602+ int err;16031603+ struct ib_cq *cq = wq->cq;16041604+ struct ib_pd *pd = wq->pd;16051605+16061606+ if (atomic_read(&wq->usecnt))16071607+ return -EBUSY;16081608+16091609+ err = wq->device->destroy_wq(wq);16101610+ if (!err) {16111611+ atomic_dec(&pd->usecnt);16121612+ atomic_dec(&cq->usecnt);16131613+ }16141614+ return err;16151615+}16161616+EXPORT_SYMBOL(ib_destroy_wq);16171617+16181618+/**16191619+ * ib_modify_wq - Modifies the specified WQ.16201620+ * @wq: The WQ to modify.16211621+ * @wq_attr: On input, specifies the WQ attributes to modify.16221622+ * @wq_attr_mask: A bit-mask used to specify which attributes of the WQ16231623+ * are being modified.16241624+ * On output, the current values of selected WQ attributes are returned.16251625+ */16261626+int ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,16271627+ u32 wq_attr_mask)16281628+{16291629+ int err;16301630+16311631+ if (!wq->device->modify_wq)16321632+ return -ENOSYS;16331633+16341634+ err = wq->device->modify_wq(wq, wq_attr, wq_attr_mask, NULL);16351635+ return err;16361636+}16371637+EXPORT_SYMBOL(ib_modify_wq);16381638+16391639+/*16401640+ * ib_create_rwq_ind_table - Creates a RQ Indirection Table.16411641+ * @device: The device on which to create the rwq indirection table.16421642+ * @ib_rwq_ind_table_init_attr: A list of initial attributes required to16431643+ * create the Indirection Table.16441644+ *16451645+ * Note: The life time of ib_rwq_ind_table_init_attr->ind_tbl is not less16461646+ * than the created ib_rwq_ind_table object and the caller is responsible16471647+ * for its memory allocation/free.16481648+ */16491649+struct ib_rwq_ind_table *ib_create_rwq_ind_table(struct ib_device *device,16501650+ struct ib_rwq_ind_table_init_attr *init_attr)16511651+{16521652+ struct ib_rwq_ind_table *rwq_ind_table;16531653+ int i;16541654+ u32 table_size;16551655+16561656+ if (!device->create_rwq_ind_table)16571657+ return ERR_PTR(-ENOSYS);16581658+16591659+ table_size = (1 << init_attr->log_ind_tbl_size);16601660+ rwq_ind_table = device->create_rwq_ind_table(device,16611661+ init_attr, NULL);16621662+ if (IS_ERR(rwq_ind_table))16631663+ return rwq_ind_table;16641664+16651665+ rwq_ind_table->ind_tbl = init_attr->ind_tbl;16661666+ rwq_ind_table->log_ind_tbl_size = init_attr->log_ind_tbl_size;16671667+ rwq_ind_table->device = device;16681668+ rwq_ind_table->uobject = NULL;16691669+ atomic_set(&rwq_ind_table->usecnt, 0);16701670+16711671+ for (i = 0; i < table_size; i++)16721672+ atomic_inc(&rwq_ind_table->ind_tbl[i]->usecnt);16731673+16741674+ return rwq_ind_table;16751675+}16761676+EXPORT_SYMBOL(ib_create_rwq_ind_table);16771677+16781678+/*16791679+ * ib_destroy_rwq_ind_table - Destroys the specified Indirection Table.16801680+ * @wq_ind_table: The Indirection Table to destroy.16811681+*/16821682+int ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *rwq_ind_table)16831683+{16841684+ int err, i;16851685+ u32 table_size = (1 << rwq_ind_table->log_ind_tbl_size);16861686+ struct ib_wq **ind_tbl = rwq_ind_table->ind_tbl;16871687+16881688+ if (atomic_read(&rwq_ind_table->usecnt))16891689+ return -EBUSY;16901690+16911691+ err = rwq_ind_table->device->destroy_rwq_ind_table(rwq_ind_table);16921692+ if (!err) {16931693+ for (i = 0; i < table_size; i++)16941694+ atomic_dec(&ind_tbl[i]->usecnt);16951695+ }16961696+16971697+ return err;16981698+}16991699+EXPORT_SYMBOL(ib_destroy_rwq_ind_table);1571170015721701struct ib_flow *ib_create_flow(struct ib_qp *qp,15731702 struct ib_flow_attr *flow_attr,