/* * Dump tempsense regs. in decimal, to ease shell-scripts. */ static ssize_t show_tempsense(struct device *device, struct device_attribute *attr, char *buf) { struct qib_ibdev *dev = container_of(device, struct qib_ibdev, rdi.ibdev.dev); struct qib_devdata *dd = dd_from_dev(dev); int ret; int idx; u8 regvals[8]; ret = -ENXIO; for (idx = 0; idx < 8; ++idx) { if (idx == 6) continue; ret = dd->f_tempsense_rd(dd, idx); if (ret < 0) break; regvals[idx] = ret; } if (idx == 8) ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n", *(signed char *)(regvals), *(signed char *)(regvals + 1), regvals[2], regvals[3], *(signed char *)(regvals + 5), *(signed char *)(regvals + 7)); return ret; }
/* * Start of per-unit (or driver, in some cases, but replicated * per unit) functions (these get a device *) */ static ssize_t show_rev(struct device *device, struct device_attribute *attr, char *buf) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev); }
static ssize_t show_serial(struct device *device, struct device_attribute *attr, char *buf) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); struct hfi1_devdata *dd = dd_from_dev(dev); return scnprintf(buf, PAGE_SIZE, "%s", dd->serial); }
static ssize_t show_nfreectxts(struct device *device, struct device_attribute *attr, char *buf) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); struct hfi1_devdata *dd = dd_from_dev(dev); /* Return the number of free user ports (contexts) available. */ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts); }
static ssize_t show_boardversion(struct device *device, struct device_attribute *attr, char *buf) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); struct hfi1_devdata *dd = dd_from_dev(dev); /* The string printed here is already newline-terminated. */ return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion); }
static ssize_t show_localbus_info(struct device *device, struct device_attribute *attr, char *buf) { struct qib_ibdev *dev = container_of(device, struct qib_ibdev, rdi.ibdev.dev); struct qib_devdata *dd = dd_from_dev(dev); /* The string printed here is already newline-terminated. */ return scnprintf(buf, PAGE_SIZE, "%s", dd->lbus_info); }
static ssize_t show_serial(struct device *device, struct device_attribute *attr, char *buf) { struct qib_ibdev *dev = container_of(device, struct qib_ibdev, rdi.ibdev.dev); struct qib_devdata *dd = dd_from_dev(dev); buf[sizeof(dd->serial)] = '\0'; memcpy(buf, dd->serial, sizeof(dd->serial)); strcat(buf, "\n"); return strlen(buf); }
static ssize_t show_hfi(struct device *device, struct device_attribute *attr, char *buf) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); struct hfi1_devdata *dd = dd_from_dev(dev); int ret; if (!dd->boardname) ret = -EINVAL; else ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname); return ret; }
static ssize_t show_nctxts(struct device *device, struct device_attribute *attr, char *buf) { struct qib_ibdev *dev = container_of(device, struct qib_ibdev, rdi.ibdev.dev); struct qib_devdata *dd = dd_from_dev(dev); /* Return the number of user ports (contexts) available. */ /* The calculation below deals with a special case where * cfgctxts is set to 1 on a single-port board. */ return scnprintf(buf, PAGE_SIZE, "%u\n", (dd->first_user_ctxt > dd->cfgctxts) ? 0 : (dd->cfgctxts - dd->first_user_ctxt)); }
static ssize_t show_nctxts(struct device *device, struct device_attribute *attr, char *buf) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); struct hfi1_devdata *dd = dd_from_dev(dev); /* * Return the smaller of send and receive contexts. * Normally, user level applications would require both a send * and a receive context, so returning the smaller of the two counts * give a more accurate picture of total contexts available. */ return scnprintf(buf, PAGE_SIZE, "%u\n", min(dd->num_rcv_contexts - dd->first_user_ctxt, (u32)dd->sc_sizes[SC_USER].count)); }
static ssize_t store_chip_reset(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); struct hfi1_devdata *dd = dd_from_dev(dev); int ret; if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) { ret = -EINVAL; goto bail; } ret = hfi1_reset_device(dd->unit); bail: return ret < 0 ? ret : count; }
void hfi1_put_txreq(struct verbs_txreq *tx) { struct hfi1_ibdev *dev; struct rvt_qp *qp; unsigned long flags; unsigned int seq; struct hfi1_qp_priv *priv; qp = tx->qp; dev = to_idev(qp->ibqp.device); if (tx->mr) rvt_put_mr(tx->mr); sdma_txclean(dd_from_dev(dev), &tx->txreq); /* Free verbs_txreq and return to slab cache */ kmem_cache_free(dev->verbs_txreq_cache, tx); do { seq = read_seqbegin(&dev->iowait_lock); if (!list_empty(&dev->txwait)) { struct iowait *wait; write_seqlock_irqsave(&dev->iowait_lock, flags); wait = list_first_entry(&dev->txwait, struct iowait, list); qp = iowait_to_qp(wait); priv = qp->priv; list_del_init(&priv->s_iowait.list); /* refcount held until actual wake up */ write_sequnlock_irqrestore(&dev->iowait_lock, flags); hfi1_qp_wakeup(qp, RVT_S_WAIT_TX); break; } } while (read_seqretry(&dev->iowait_lock, seq)); }
/* * Dump tempsense values, in decimal, to ease shell-scripts. */ static ssize_t show_tempsense(struct device *device, struct device_attribute *attr, char *buf) { struct hfi1_ibdev *dev = container_of(device, struct hfi1_ibdev, rdi.ibdev.dev); struct hfi1_devdata *dd = dd_from_dev(dev); struct hfi1_temp temp; int ret; ret = hfi1_tempsense_rd(dd, &temp); if (!ret) { int idx = 0; idx += temp2str(temp.curr, buf, PAGE_SIZE, idx); idx += temp2str(temp.lo_lim, buf, PAGE_SIZE, idx); idx += temp2str(temp.hi_lim, buf, PAGE_SIZE, idx); idx += temp2str(temp.crit_lim, buf, PAGE_SIZE, idx); idx += scnprintf(buf + idx, PAGE_SIZE - idx, "%u %u %u\n", temp.triggers & 0x1, temp.triggers & 0x2, temp.triggers & 0x4); ret = idx; } return ret; }
int hfi1_check_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr, int attr_mask, struct ib_udata *udata) { struct ib_qp *ibqp = &qp->ibqp; struct hfi1_ibdev *dev = to_idev(ibqp->device); struct hfi1_devdata *dd = dd_from_dev(dev); u8 sc; if (attr_mask & IB_QP_AV) { sc = ah_to_sc(ibqp->device, &attr->ah_attr); if (sc == 0xf) return -EINVAL; if (!qp_to_sdma_engine(qp, sc) && dd->flags & HFI1_HAS_SEND_DMA) return -EINVAL; if (!qp_to_send_context(qp, sc)) return -EINVAL; } if (attr_mask & IB_QP_ALT_PATH) { sc = ah_to_sc(ibqp->device, &attr->alt_ah_attr); if (sc == 0xf) return -EINVAL; if (!qp_to_sdma_engine(qp, sc) && dd->flags & HFI1_HAS_SEND_DMA) return -EINVAL; if (!qp_to_send_context(qp, sc)) return -EINVAL; } return 0; }
/** * hfi1_modify_qp - modify the attributes of a queue pair * @ibqp: the queue pair who's attributes we're modifying * @attr: the new attributes * @attr_mask: the mask of attributes to modify * @udata: user data for libibverbs.so * * Returns 0 on success, otherwise returns an errno. */ int hfi1_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_udata *udata) { struct hfi1_ibdev *dev = to_idev(ibqp->device); struct hfi1_qp *qp = to_iqp(ibqp); enum ib_qp_state cur_state, new_state; struct ib_event ev; int lastwqe = 0; int mig = 0; int ret; u32 pmtu = 0; /* for gcc warning only */ struct hfi1_devdata *dd; spin_lock_irq(&qp->r_lock); spin_lock(&qp->s_lock); cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask, IB_LINK_LAYER_UNSPECIFIED)) goto inval; if (attr_mask & IB_QP_AV) { if (attr->ah_attr.dlid >= HFI1_MULTICAST_LID_BASE) goto inval; if (hfi1_check_ah(qp->ibqp.device, &attr->ah_attr)) goto inval; } if (attr_mask & IB_QP_ALT_PATH) { if (attr->alt_ah_attr.dlid >= HFI1_MULTICAST_LID_BASE) goto inval; if (hfi1_check_ah(qp->ibqp.device, &attr->alt_ah_attr)) goto inval; if (attr->alt_pkey_index >= hfi1_get_npkeys(dd_from_dev(dev))) goto inval; } if (attr_mask & IB_QP_PKEY_INDEX) if (attr->pkey_index >= hfi1_get_npkeys(dd_from_dev(dev))) goto inval; if (attr_mask & IB_QP_MIN_RNR_TIMER) if (attr->min_rnr_timer > 31) goto inval; if (attr_mask & IB_QP_PORT) if (qp->ibqp.qp_type == IB_QPT_SMI || qp->ibqp.qp_type == IB_QPT_GSI || attr->port_num == 0 || attr->port_num > ibqp->device->phys_port_cnt) goto inval; if (attr_mask & IB_QP_DEST_QPN) if (attr->dest_qp_num > HFI1_QPN_MASK) goto inval; if (attr_mask & IB_QP_RETRY_CNT) if (attr->retry_cnt > 7) goto inval; if (attr_mask & IB_QP_RNR_RETRY) if (attr->rnr_retry > 7) goto inval; /* * Don't allow invalid path_mtu values. OK to set greater * than the active mtu (or even the max_cap, if we have tuned * that to a small mtu. We'll set qp->path_mtu * to the lesser of requested attribute mtu and active, * for packetizing messages. * Note that the QP port has to be set in INIT and MTU in RTR. */ if (attr_mask & IB_QP_PATH_MTU) { int mtu, pidx = qp->port_num - 1; dd = dd_from_dev(dev); mtu = verbs_mtu_enum_to_int(ibqp->device, attr->path_mtu); if (mtu == -1) goto inval; if (mtu > dd->pport[pidx].ibmtu) pmtu = mtu_to_enum(dd->pport[pidx].ibmtu, IB_MTU_2048); else pmtu = attr->path_mtu; } if (attr_mask & IB_QP_PATH_MIG_STATE) { if (attr->path_mig_state == IB_MIG_REARM) { if (qp->s_mig_state == IB_MIG_ARMED) goto inval; if (new_state != IB_QPS_RTS) goto inval; } else if (attr->path_mig_state == IB_MIG_MIGRATED) { if (qp->s_mig_state == IB_MIG_REARM) goto inval; if (new_state != IB_QPS_RTS && new_state != IB_QPS_SQD) goto inval; if (qp->s_mig_state == IB_MIG_ARMED) mig = 1; } else goto inval; } if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) if (attr->max_dest_rd_atomic > HFI1_MAX_RDMA_ATOMIC) goto inval; switch (new_state) { case IB_QPS_RESET: if (qp->state != IB_QPS_RESET) { qp->state = IB_QPS_RESET; flush_iowait(qp); qp->s_flags &= ~(HFI1_S_TIMER | HFI1_S_ANY_WAIT); spin_unlock(&qp->s_lock); spin_unlock_irq(&qp->r_lock); /* Stop the sending work queue and retry timer */ cancel_work_sync(&qp->s_iowait.iowork); del_timer_sync(&qp->s_timer); iowait_sdma_drain(&qp->s_iowait); flush_tx_list(qp); remove_qp(dev, qp); wait_event(qp->wait, !atomic_read(&qp->refcount)); spin_lock_irq(&qp->r_lock); spin_lock(&qp->s_lock); clear_mr_refs(qp, 1); clear_ahg(qp); reset_qp(qp, ibqp->qp_type); } break; case IB_QPS_RTR: /* Allow event to re-trigger if QP set to RTR more than once */ qp->r_flags &= ~HFI1_R_COMM_EST; qp->state = new_state; break; case IB_QPS_SQD: qp->s_draining = qp->s_last != qp->s_cur; qp->state = new_state; break; case IB_QPS_SQE: if (qp->ibqp.qp_type == IB_QPT_RC) goto inval; qp->state = new_state; break; case IB_QPS_ERR: lastwqe = hfi1_error_qp(qp, IB_WC_WR_FLUSH_ERR); break; default: qp->state = new_state; break; } if (attr_mask & IB_QP_PKEY_INDEX) qp->s_pkey_index = attr->pkey_index; if (attr_mask & IB_QP_PORT) qp->port_num = attr->port_num; if (attr_mask & IB_QP_DEST_QPN) qp->remote_qpn = attr->dest_qp_num; if (attr_mask & IB_QP_SQ_PSN) { qp->s_next_psn = attr->sq_psn & PSN_MODIFY_MASK; qp->s_psn = qp->s_next_psn; qp->s_sending_psn = qp->s_next_psn; qp->s_last_psn = qp->s_next_psn - 1; qp->s_sending_hpsn = qp->s_last_psn; } if (attr_mask & IB_QP_RQ_PSN) qp->r_psn = attr->rq_psn & PSN_MODIFY_MASK; if (attr_mask & IB_QP_ACCESS_FLAGS) qp->qp_access_flags = attr->qp_access_flags; if (attr_mask & IB_QP_AV) { qp->remote_ah_attr = attr->ah_attr; qp->s_srate = attr->ah_attr.static_rate; qp->srate_mbps = ib_rate_to_mbps(qp->s_srate); } if (attr_mask & IB_QP_ALT_PATH) { qp->alt_ah_attr = attr->alt_ah_attr; qp->s_alt_pkey_index = attr->alt_pkey_index; } if (attr_mask & IB_QP_PATH_MIG_STATE) { qp->s_mig_state = attr->path_mig_state; if (mig) { qp->remote_ah_attr = qp->alt_ah_attr; qp->port_num = qp->alt_ah_attr.port_num; qp->s_pkey_index = qp->s_alt_pkey_index; qp->s_flags |= HFI1_S_AHG_CLEAR; } } if (attr_mask & IB_QP_PATH_MTU) { struct hfi1_ibport *ibp; u8 sc, vl; u32 mtu; dd = dd_from_dev(dev); ibp = &dd->pport[qp->port_num - 1].ibport_data; sc = ibp->sl_to_sc[qp->remote_ah_attr.sl]; vl = sc_to_vlt(dd, sc); mtu = verbs_mtu_enum_to_int(ibqp->device, pmtu); if (vl < PER_VL_SEND_CONTEXTS) mtu = min_t(u32, mtu, dd->vld[vl].mtu); pmtu = mtu_to_enum(mtu, OPA_MTU_8192); qp->path_mtu = pmtu; qp->pmtu = mtu; } if (attr_mask & IB_QP_RETRY_CNT) { qp->s_retry_cnt = attr->retry_cnt; qp->s_retry = attr->retry_cnt; } if (attr_mask & IB_QP_RNR_RETRY) { qp->s_rnr_retry_cnt = attr->rnr_retry; qp->s_rnr_retry = attr->rnr_retry; } if (attr_mask & IB_QP_MIN_RNR_TIMER) qp->r_min_rnr_timer = attr->min_rnr_timer; if (attr_mask & IB_QP_TIMEOUT) { qp->timeout = attr->timeout; qp->timeout_jiffies = usecs_to_jiffies((4096UL * (1UL << qp->timeout)) / 1000UL); } if (attr_mask & IB_QP_QKEY) qp->qkey = attr->qkey; if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) qp->r_max_rd_atomic = attr->max_dest_rd_atomic; if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) qp->s_max_rd_atomic = attr->max_rd_atomic; spin_unlock(&qp->s_lock); spin_unlock_irq(&qp->r_lock); if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) insert_qp(dev, qp); if (lastwqe) { ev.device = qp->ibqp.device; ev.element.qp = &qp->ibqp; ev.event = IB_EVENT_QP_LAST_WQE_REACHED; qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); } if (mig) { ev.device = qp->ibqp.device; ev.element.qp = &qp->ibqp; ev.event = IB_EVENT_PATH_MIG; qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); } ret = 0; goto bail; inval: spin_unlock(&qp->s_lock); spin_unlock_irq(&qp->r_lock); ret = -EINVAL; bail: return ret; }
/** * hfi1_create_qp - create a queue pair for a device * @ibpd: the protection domain who's device we create the queue pair for * @init_attr: the attributes of the queue pair * @udata: user data for libibverbs.so * * Returns the queue pair on success, otherwise returns an errno. * * Called by the ib_create_qp() core verbs function. */ struct ib_qp *hfi1_create_qp(struct ib_pd *ibpd, struct ib_qp_init_attr *init_attr, struct ib_udata *udata) { struct hfi1_qp *qp; int err; struct hfi1_swqe *swq = NULL; struct hfi1_ibdev *dev; struct hfi1_devdata *dd; size_t sz; size_t sg_list_sz; struct ib_qp *ret; if (init_attr->cap.max_send_sge > hfi1_max_sges || init_attr->cap.max_send_wr > hfi1_max_qp_wrs || init_attr->create_flags) { ret = ERR_PTR(-EINVAL); goto bail; } /* Check receive queue parameters if no SRQ is specified. */ if (!init_attr->srq) { if (init_attr->cap.max_recv_sge > hfi1_max_sges || init_attr->cap.max_recv_wr > hfi1_max_qp_wrs) { ret = ERR_PTR(-EINVAL); goto bail; } if (init_attr->cap.max_send_sge + init_attr->cap.max_send_wr + init_attr->cap.max_recv_sge + init_attr->cap.max_recv_wr == 0) { ret = ERR_PTR(-EINVAL); goto bail; } } switch (init_attr->qp_type) { case IB_QPT_SMI: case IB_QPT_GSI: if (init_attr->port_num == 0 || init_attr->port_num > ibpd->device->phys_port_cnt) { ret = ERR_PTR(-EINVAL); goto bail; } case IB_QPT_UC: case IB_QPT_RC: case IB_QPT_UD: sz = sizeof(struct hfi1_sge) * init_attr->cap.max_send_sge + sizeof(struct hfi1_swqe); swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz); if (swq == NULL) { ret = ERR_PTR(-ENOMEM); goto bail; } sz = sizeof(*qp); sg_list_sz = 0; if (init_attr->srq) { struct hfi1_srq *srq = to_isrq(init_attr->srq); if (srq->rq.max_sge > 1) sg_list_sz = sizeof(*qp->r_sg_list) * (srq->rq.max_sge - 1); } 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); if (!qp) { ret = ERR_PTR(-ENOMEM); goto bail_swq; } RCU_INIT_POINTER(qp->next, NULL); qp->s_hdr = kzalloc(sizeof(*qp->s_hdr), GFP_KERNEL); if (!qp->s_hdr) { ret = ERR_PTR(-ENOMEM); goto bail_qp; } qp->timeout_jiffies = usecs_to_jiffies((4096UL * (1UL << qp->timeout)) / 1000UL); if (init_attr->srq) sz = 0; else { qp->r_rq.size = init_attr->cap.max_recv_wr + 1; qp->r_rq.max_sge = init_attr->cap.max_recv_sge; sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) + sizeof(struct hfi1_rwqe); qp->r_rq.wq = vmalloc_user(sizeof(struct hfi1_rwq) + qp->r_rq.size * sz); if (!qp->r_rq.wq) { ret = ERR_PTR(-ENOMEM); goto bail_qp; } } /* * ib_create_qp() will initialize qp->ibqp * except for qp->ibqp.qp_num. */ spin_lock_init(&qp->r_lock); spin_lock_init(&qp->s_lock); spin_lock_init(&qp->r_rq.lock); atomic_set(&qp->refcount, 0); init_waitqueue_head(&qp->wait); init_timer(&qp->s_timer); qp->s_timer.data = (unsigned long)qp; INIT_LIST_HEAD(&qp->rspwait); qp->state = IB_QPS_RESET; qp->s_wq = swq; qp->s_size = init_attr->cap.max_send_wr + 1; qp->s_max_sge = init_attr->cap.max_send_sge; if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR) qp->s_flags = HFI1_S_SIGNAL_REQ_WR; dev = to_idev(ibpd->device); dd = dd_from_dev(dev); err = alloc_qpn(dd, &dev->qp_dev->qpn_table, init_attr->qp_type, init_attr->port_num); if (err < 0) { ret = ERR_PTR(err); vfree(qp->r_rq.wq); goto bail_qp; } qp->ibqp.qp_num = err; qp->port_num = init_attr->port_num; reset_qp(qp, init_attr->qp_type); break; default: /* Don't support raw QPs */ ret = ERR_PTR(-ENOSYS); goto bail; } init_attr->cap.max_inline_data = 0; /* * Return the address of the RWQ as the offset to mmap. * See hfi1_mmap() for details. */ if (udata && udata->outlen >= sizeof(__u64)) { if (!qp->r_rq.wq) { __u64 offset = 0; err = ib_copy_to_udata(udata, &offset, sizeof(offset)); if (err) { ret = ERR_PTR(err); goto bail_ip; } } else { u32 s = sizeof(struct hfi1_rwq) + qp->r_rq.size * sz; qp->ip = hfi1_create_mmap_info(dev, s, ibpd->uobject->context, qp->r_rq.wq); if (!qp->ip) { ret = ERR_PTR(-ENOMEM); goto bail_ip; } err = ib_copy_to_udata(udata, &(qp->ip->offset), sizeof(qp->ip->offset)); if (err) { ret = ERR_PTR(err); goto bail_ip; } } } spin_lock(&dev->n_qps_lock); if (dev->n_qps_allocated == hfi1_max_qps) { spin_unlock(&dev->n_qps_lock); ret = ERR_PTR(-ENOMEM); goto bail_ip; } dev->n_qps_allocated++; spin_unlock(&dev->n_qps_lock); if (qp->ip) { spin_lock_irq(&dev->pending_lock); list_add(&qp->ip->pending_mmaps, &dev->pending_mmaps); spin_unlock_irq(&dev->pending_lock); } ret = &qp->ibqp; /* * We have our QP and its good, now keep track of what types of opcodes * can be processed on this QP. We do this by keeping track of what the * 3 high order bits of the opcode are. */ switch (init_attr->qp_type) { case IB_QPT_SMI: case IB_QPT_GSI: case IB_QPT_UD: qp->allowed_ops = IB_OPCODE_UD_SEND_ONLY & OPCODE_QP_MASK; break; case IB_QPT_RC: qp->allowed_ops = IB_OPCODE_RC_SEND_ONLY & OPCODE_QP_MASK; break; case IB_QPT_UC: qp->allowed_ops = IB_OPCODE_UC_SEND_ONLY & OPCODE_QP_MASK; break; default: ret = ERR_PTR(-EINVAL); goto bail_ip; } goto bail; bail_ip: if (qp->ip) kref_put(&qp->ip->ref, hfi1_release_mmap_info); else vfree(qp->r_rq.wq); free_qpn(&dev->qp_dev->qpn_table, qp->ibqp.qp_num); bail_qp: kfree(qp->s_hdr); kfree(qp); bail_swq: vfree(swq); bail: return ret; }