projects
/
linux.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
IB/qib: Avoid returning EBUSY from MR deregister
[linux.git]
/
drivers
/
infiniband
/
hw
/
qib
/
qib_keys.c
diff --git
a/drivers/infiniband/hw/qib/qib_keys.c
b/drivers/infiniband/hw/qib/qib_keys.c
index 8fd19a47df0c76a7d7527f302d32449c6bdbec4d..8b5ee3aa8e3dabea31d7a3f5fe3e8fba57f3f23e 100644
(file)
--- a/
drivers/infiniband/hw/qib/qib_keys.c
+++ b/
drivers/infiniband/hw/qib/qib_keys.c
@@
-35,21
+35,40
@@
/**
* qib_alloc_lkey - allocate an lkey
/**
* qib_alloc_lkey - allocate an lkey
- * @rkt: lkey table in which to allocate the lkey
* @mr: memory region that this lkey protects
* @mr: memory region that this lkey protects
+ * @dma_region: 0->normal key, 1->restricted DMA key
+ *
+ * Returns 0 if successful, otherwise returns -errno.
+ *
+ * Increments mr reference count and sets published
+ * as required.
+ *
+ * Sets the lkey field mr for non-dma regions.
*
*
- * Returns 1 if successful, otherwise returns 0.
*/
*/
-int qib_alloc_lkey(struct qib_
lkey_table *rkt, struct qib_mregion *mr
)
+int qib_alloc_lkey(struct qib_
mregion *mr, int dma_region
)
{
unsigned long flags;
u32 r;
u32 n;
{
unsigned long flags;
u32 r;
u32 n;
- int ret;
+ int ret = 0;
+ struct qib_ibdev *dev = to_idev(mr->pd->device);
+ struct qib_lkey_table *rkt = &dev->lk_table;
spin_lock_irqsave(&rkt->lock, flags);
spin_lock_irqsave(&rkt->lock, flags);
+ /* special case for dma_mr lkey == 0 */
+ if (dma_region) {
+ /* should the dma_mr be relative to the pd? */
+ if (!dev->dma_mr) {
+ qib_get_mr(mr);
+ dev->dma_mr = mr;
+ mr->lkey_published = 1;
+ }
+ goto success;
+ }
+
/* Find the next available LKEY */
r = rkt->next;
n = r;
/* Find the next available LKEY */
r = rkt->next;
n = r;
@@
-57,11
+76,8
@@
int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr)
if (rkt->table[r] == NULL)
break;
r = (r + 1) & (rkt->max - 1);
if (rkt->table[r] == NULL)
break;
r = (r + 1) & (rkt->max - 1);
- if (r == n) {
- spin_unlock_irqrestore(&rkt->lock, flags);
- ret = 0;
+ if (r == n)
goto bail;
goto bail;
- }
}
rkt->next = (r + 1) & (rkt->max - 1);
/*
}
rkt->next = (r + 1) & (rkt->max - 1);
/*
@@
-76,46
+92,50
@@
int qib_alloc_lkey(struct qib_lkey_table *rkt, struct qib_mregion *mr)
mr->lkey |= 1 << 8;
rkt->gen++;
}
mr->lkey |= 1 << 8;
rkt->gen++;
}
+ qib_get_mr(mr);
rkt->table[r] = mr;
rkt->table[r] = mr;
+ mr->lkey_published = 1;
+success:
spin_unlock_irqrestore(&rkt->lock, flags);
spin_unlock_irqrestore(&rkt->lock, flags);
-
- ret = 1;
-
-bail:
+out:
return ret;
return ret;
+bail:
+ spin_unlock_irqrestore(&rkt->lock, flags);
+ ret = -ENOMEM;
+ goto out;
}
/**
* qib_free_lkey - free an lkey
}
/**
* qib_free_lkey - free an lkey
- * @rkt: table from which to free the lkey
- * @lkey: lkey id to free
+ * @mr: mr to free from tables
*/
*/
-
int qib_free_lkey(struct qib_ibdev *dev,
struct qib_mregion *mr)
+
void qib_free_lkey(
struct qib_mregion *mr)
{
unsigned long flags;
u32 lkey = mr->lkey;
u32 r;
{
unsigned long flags;
u32 lkey = mr->lkey;
u32 r;
- int ret;
+ struct qib_ibdev *dev = to_idev(mr->pd->device);
+ struct qib_lkey_table *rkt = &dev->lk_table;
+
+ spin_lock_irqsave(&rkt->lock, flags);
+ if (!mr->lkey_published)
+ goto out;
+ mr->lkey_published = 0;
+
spin_lock_irqsave(&dev->lk_table.lock, flags);
if (lkey == 0) {
if (dev->dma_mr && dev->dma_mr == mr) {
spin_lock_irqsave(&dev->lk_table.lock, flags);
if (lkey == 0) {
if (dev->dma_mr && dev->dma_mr == mr) {
- ret = atomic_read(&dev->dma_mr->refcount);
- if (!ret)
- dev->dma_mr = NULL;
- } else
- ret = 0;
+ qib_put_mr(dev->dma_mr);
+ dev->dma_mr = NULL;
+ }
} else {
r = lkey >> (32 - ib_qib_lkey_table_size);
} else {
r = lkey >> (32 - ib_qib_lkey_table_size);
- ret = atomic_read(&dev->lk_table.table[r]->refcount);
- if (!ret)
- dev->lk_table.table[r] = NULL;
+ qib_put_mr(dev->dma_mr);
+ rkt->table[r] = NULL;
}
}
+out:
spin_unlock_irqrestore(&dev->lk_table.lock, flags);
spin_unlock_irqrestore(&dev->lk_table.lock, flags);
-
- if (ret)
- ret = -EBUSY;
- return ret;
}
/**
}
/**
@@
-150,7
+170,7
@@
int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd,
goto bail;
if (!dev->dma_mr)
goto bail;
goto bail;
if (!dev->dma_mr)
goto bail;
-
atomic_inc(&dev->dma_mr->refcount
);
+
qib_get_mr(dev->dma_mr
);
spin_unlock_irqrestore(&rkt->lock, flags);
isge->mr = dev->dma_mr;
spin_unlock_irqrestore(&rkt->lock, flags);
isge->mr = dev->dma_mr;
@@
-171,7
+191,7
@@
int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd,
off + sge->length > mr->length ||
(mr->access_flags & acc) != acc))
goto bail;
off + sge->length > mr->length ||
(mr->access_flags & acc) != acc))
goto bail;
-
atomic_inc(&mr->refcount
);
+
qib_get_mr(mr
);
spin_unlock_irqrestore(&rkt->lock, flags);
off += mr->offset;
spin_unlock_irqrestore(&rkt->lock, flags);
off += mr->offset;
@@
-245,7
+265,7
@@
int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge,
goto bail;
if (!dev->dma_mr)
goto bail;
goto bail;
if (!dev->dma_mr)
goto bail;
-
atomic_inc(&dev->dma_mr->refcount
);
+
qib_get_mr(dev->dma_mr
);
spin_unlock_irqrestore(&rkt->lock, flags);
sge->mr = dev->dma_mr;
spin_unlock_irqrestore(&rkt->lock, flags);
sge->mr = dev->dma_mr;
@@
-265,7
+285,7
@@
int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge,
if (unlikely(vaddr < mr->iova || off + len > mr->length ||
(mr->access_flags & acc) == 0))
goto bail;
if (unlikely(vaddr < mr->iova || off + len > mr->length ||
(mr->access_flags & acc) == 0))
goto bail;
-
atomic_inc(&mr->refcount
);
+
qib_get_mr(mr
);
spin_unlock_irqrestore(&rkt->lock, flags);
off += mr->offset;
spin_unlock_irqrestore(&rkt->lock, flags);
off += mr->offset;