/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
if ((unsigned) wr->num_sge > srq->rq.max_sge) {
*bad_wr = wr;
- ret = -ENOMEM;
+ ret = -EINVAL;
goto bail;
}
wqe->num_sge = wr->num_sge;
for (i = 0; i < wr->num_sge; i++)
wqe->sg_list[i] = wr->sg_list[i];
+ /* Make sure queue entry is written before the head index. */
+ smp_wmb();
wq->head = next;
spin_unlock_irqrestore(&srq->rq.lock, flags);
}
/**
* ipath_create_srq - create a shared receive queue
* @ibpd: the protection domain of the SRQ to create
- * @attr: the attributes of the SRQ
- * @udata: not used by the InfiniPath verbs driver
+ * @srq_init_attr: the attributes of the SRQ
+ * @udata: data from libipathverbs when creating a user SRQ
*/
struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
struct ib_srq_init_attr *srq_init_attr,
struct ib_udata *udata)
{
struct ipath_srq *srq = to_isrq(ibsrq);
+ struct ipath_rwq *wq;
int ret = 0;
if (attr_mask & IB_SRQ_MAX_WR) {
struct ipath_rwq *owq;
- struct ipath_rwq *wq;
struct ipath_rwqe *p;
u32 sz, size, n, head, tail;
goto bail;
}
- /*
- * Return the address of the RWQ as the offset to mmap.
- * See ipath_mmap() for details.
- */
+ /* Check that we can write the offset to mmap. */
if (udata && udata->inlen >= sizeof(__u64)) {
__u64 offset_addr;
- __u64 offset = (__u64) wq;
+ __u64 offset = 0;
ret = ib_copy_from_udata(&offset_addr, udata,
sizeof(offset_addr));
- if (ret) {
- vfree(wq);
- goto bail;
- }
- udata->outbuf = (void __user *) offset_addr;
+ if (ret)
+ goto bail_free;
+ udata->outbuf =
+ (void __user *) (unsigned long) offset_addr;
ret = ib_copy_to_udata(udata, &offset,
sizeof(offset));
- if (ret) {
- vfree(wq);
- goto bail;
- }
+ if (ret)
+ goto bail_free;
}
spin_lock_irq(&srq->rq.lock);
else
n -= tail;
if (size <= n) {
- spin_unlock_irq(&srq->rq.lock);
- vfree(wq);
ret = -EINVAL;
- goto bail;
+ goto bail_unlock;
}
n = 0;
p = wq->wq;
u32 s = sizeof(struct ipath_rwq) + size * sz;
ipath_update_mmap_info(dev, ip, s, wq);
+
+ /*
+ * Return the offset to mmap.
+ * See ipath_mmap() for details.
+ */
+ if (udata && udata->inlen >= sizeof(__u64)) {
+ ret = ib_copy_to_udata(udata, &ip->offset,
+ sizeof(ip->offset));
+ if (ret)
+ goto bail;
+ }
+
spin_lock_irq(&dev->pending_lock);
if (list_empty(&ip->pending_mmaps))
list_add(&ip->pending_mmaps,
srq->limit = attr->srq_limit;
spin_unlock_irq(&srq->rq.lock);
}
+ goto bail;
+bail_unlock:
+ spin_unlock_irq(&srq->rq.lock);
+bail_free:
+ vfree(wq);
bail:
return ret;
}