static int iwch_destroy_cq(struct ib_cq *ib_cq) { struct iwch_cq *chp; PDBG("%s ib_cq %p\n", __FUNCTION__, ib_cq); chp = to_iwch_cq(ib_cq); remove_handle(chp->rhp, &chp->rhp->cqidr, chp->cq.cqid); atomic_dec(&chp->refcnt); wait_event(chp->wait, !atomic_read(&chp->refcnt)); cxio_destroy_cq(&chp->rhp->rdev, &chp->cq); kfree(chp); return 0; }
static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) { #ifdef notyet struct iwch_cq *chp = to_iwch_cq(cq); struct t3_cq oldcq, newcq; int ret; PDBG("%s ib_cq %p cqe %d\n", __FUNCTION__, cq, cqe); /* We don't downsize... */ if (cqe <= cq->cqe) return 0; /* create new t3_cq with new size */ cqe = roundup_pow_of_two(cqe+1); newcq.size_log2 = ilog2(cqe); /* Dont allow resize to less than the current wce count */ if (cqe < Q_COUNT(chp->cq.rptr, chp->cq.wptr)) { return -ENOMEM; } /* Quiesce all QPs using this CQ */ ret = iwch_quiesce_qps(chp); if (ret) { return ret; } ret = cxio_create_cq(&chp->rhp->rdev, &newcq); if (ret) { return ret; } /* copy CQEs */ memcpy(newcq.queue, chp->cq.queue, (1 << chp->cq.size_log2) * sizeof(struct t3_cqe)); /* old iwch_qp gets new t3_cq but keeps old cqid */ oldcq = chp->cq; chp->cq = newcq; chp->cq.cqid = oldcq.cqid; /* resize new t3_cq to update the HW context */ ret = cxio_resize_cq(&chp->rhp->rdev, &chp->cq); if (ret) { chp->cq = oldcq; return ret; } chp->ibcq.cqe = (1<<chp->cq.size_log2) - 1; /* destroy old t3_cq */ oldcq.cqid = newcq.cqid; ret = cxio_destroy_cq(&chp->rhp->rdev, &oldcq); if (ret) { printk(KERN_ERR MOD "%s - cxio_destroy_cq failed %d\n", __FUNCTION__, ret); } /* add user hooks here */ /* resume qps */ ret = iwch_resume_qps(chp); return ret; #else return -ENOSYS; #endif }
static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) { #ifdef notyet struct iwch_cq *chp = to_iwch_cq(cq); struct t3_cq oldcq, newcq; int ret; PDBG("%s ib_cq %p cqe %d\n", __func__, cq, cqe); if (cqe <= cq->cqe) return 0; cqe = roundup_pow_of_two(cqe+1); newcq.size_log2 = ilog2(cqe); if (cqe < Q_COUNT(chp->cq.rptr, chp->cq.wptr)) { return -ENOMEM; } ret = iwch_quiesce_qps(chp); if (ret) { return ret; } ret = cxio_create_cq(&chp->rhp->rdev, &newcq); if (ret) { return ret; } memcpy(newcq.queue, chp->cq.queue, (1 << chp->cq.size_log2) * sizeof(struct t3_cqe)); oldcq = chp->cq; chp->cq = newcq; chp->cq.cqid = oldcq.cqid; ret = cxio_resize_cq(&chp->rhp->rdev, &chp->cq); if (ret) { chp->cq = oldcq; return ret; } chp->ibcq.cqe = (1<<chp->cq.size_log2) - 1; oldcq.cqid = newcq.cqid; ret = cxio_destroy_cq(&chp->rhp->rdev, &oldcq); if (ret) { printk(KERN_ERR MOD "%s - cxio_destroy_cq failed %d\n", __func__, ret); } ret = iwch_resume_qps(chp); return ret; #else return -ENOSYS; #endif }
static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, const struct ib_cq_init_attr *attr, struct ib_ucontext *ib_context, struct ib_udata *udata) { int entries = attr->cqe; struct iwch_dev *rhp; struct iwch_cq *chp; struct iwch_create_cq_resp uresp; struct iwch_create_cq_req ureq; struct iwch_ucontext *ucontext = NULL; static int warned; size_t resplen; PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); if (attr->flags) return ERR_PTR(-EINVAL); rhp = to_iwch_dev(ibdev); chp = kzalloc(sizeof(*chp), GFP_KERNEL); if (!chp) return ERR_PTR(-ENOMEM); if (ib_context) { ucontext = to_iwch_ucontext(ib_context); if (!t3a_device(rhp)) { if (ib_copy_from_udata(&ureq, udata, sizeof (ureq))) { kfree(chp); return ERR_PTR(-EFAULT); } chp->user_rptr_addr = (u32 __user *)(unsigned long)ureq.user_rptr_addr; } } if (t3a_device(rhp)) { /* * T3A: Add some fluff to handle extra CQEs inserted * for various errors. * Additional CQE possibilities: * TERMINATE, * incoming RDMA WRITE Failures * incoming RDMA READ REQUEST FAILUREs * NOTE: We cannot ensure the CQ won't overflow. */ entries += 16; } entries = roundup_pow_of_two(entries); chp->cq.size_log2 = ilog2(entries); if (cxio_create_cq(&rhp->rdev, &chp->cq, !ucontext)) { kfree(chp); return ERR_PTR(-ENOMEM); } chp->rhp = rhp; chp->ibcq.cqe = 1 << chp->cq.size_log2; spin_lock_init(&chp->lock); spin_lock_init(&chp->comp_handler_lock); atomic_set(&chp->refcnt, 1); init_waitqueue_head(&chp->wait); if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) { cxio_destroy_cq(&chp->rhp->rdev, &chp->cq); kfree(chp); return ERR_PTR(-ENOMEM); } if (ucontext) { struct iwch_mm_entry *mm; mm = kmalloc(sizeof *mm, GFP_KERNEL); if (!mm) { iwch_destroy_cq(&chp->ibcq); return ERR_PTR(-ENOMEM); } uresp.cqid = chp->cq.cqid; uresp.size_log2 = chp->cq.size_log2; spin_lock(&ucontext->mmap_lock); uresp.key = ucontext->key; ucontext->key += PAGE_SIZE; spin_unlock(&ucontext->mmap_lock); mm->key = uresp.key; mm->addr = virt_to_phys(chp->cq.queue); if (udata->outlen < sizeof uresp) { if (!warned++) printk(KERN_WARNING MOD "Warning - " "downlevel libcxgb3 (non-fatal).\n"); mm->len = PAGE_ALIGN((1UL << uresp.size_log2) * sizeof(struct t3_cqe)); resplen = sizeof(struct iwch_create_cq_resp_v0); } else { mm->len = PAGE_ALIGN(((1UL << uresp.size_log2) + 1) * sizeof(struct t3_cqe)); uresp.memsize = mm->len; uresp.reserved = 0; resplen = sizeof uresp; } if (ib_copy_to_udata(udata, &uresp, resplen)) { kfree(mm); iwch_destroy_cq(&chp->ibcq); return ERR_PTR(-EFAULT); } insert_mmap(ucontext, mm); } PDBG("created cqid 0x%0x chp %p size 0x%0x, dma_addr 0x%0llx\n", chp->cq.cqid, chp, (1 << chp->cq.size_log2), (unsigned long long) chp->cq.dma_addr); return &chp->ibcq; }
static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int vector, struct ib_ucontext *ib_context, struct ib_udata *udata) { struct iwch_dev *rhp; struct iwch_cq *chp; struct iwch_create_cq_resp uresp; struct iwch_create_cq_req ureq; struct iwch_ucontext *ucontext = NULL; PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); rhp = to_iwch_dev(ibdev); chp = kzalloc(sizeof(*chp), GFP_KERNEL); if (!chp) return ERR_PTR(-ENOMEM); if (ib_context) { ucontext = to_iwch_ucontext(ib_context); if (!t3a_device(rhp)) { if (ib_copy_from_udata(&ureq, udata, sizeof (ureq))) { kfree(chp); return ERR_PTR(-EFAULT); } chp->user_rptr_addr = (u32 __user *)(unsigned long)ureq.user_rptr_addr; } } if (t3a_device(rhp)) { entries += 16; } entries = roundup_pow_of_two(entries); chp->cq.size_log2 = ilog2(entries); if (cxio_create_cq(&rhp->rdev, &chp->cq)) { kfree(chp); return ERR_PTR(-ENOMEM); } chp->rhp = rhp; chp->ibcq.cqe = 1 << chp->cq.size_log2; spin_lock_init(&chp->lock); atomic_set(&chp->refcnt, 1); init_waitqueue_head(&chp->wait); if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) { cxio_destroy_cq(&chp->rhp->rdev, &chp->cq); kfree(chp); return ERR_PTR(-ENOMEM); } if (ucontext) { struct iwch_mm_entry *mm; mm = kmalloc(sizeof *mm, GFP_KERNEL); if (!mm) { iwch_destroy_cq(&chp->ibcq); return ERR_PTR(-ENOMEM); } uresp.cqid = chp->cq.cqid; uresp.size_log2 = chp->cq.size_log2; spin_lock(&ucontext->mmap_lock); uresp.key = ucontext->key; ucontext->key += PAGE_SIZE; spin_unlock(&ucontext->mmap_lock); if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) { kfree(mm); iwch_destroy_cq(&chp->ibcq); return ERR_PTR(-EFAULT); } mm->key = uresp.key; mm->addr = virt_to_phys(chp->cq.queue); mm->len = PAGE_ALIGN((1UL << uresp.size_log2) * sizeof (struct t3_cqe)); insert_mmap(ucontext, mm); } PDBG("created cqid 0x%0x chp %p size 0x%0x, dma_addr 0x%0llx\n", chp->cq.cqid, chp, (1 << chp->cq.size_log2), (unsigned long long) chp->cq.dma_addr); return &chp->ibcq; }