Skip to content

Commit

Permalink
IB/ehca: Change idr spinlocks into rwlocks
Browse files Browse the repository at this point in the history
This eliminates lock contention among IRQs as well as the need to
disable IRQs around idr_find, because there are no IRQ writers.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Joachim Fenkes authored and Roland Dreier committed Jul 10, 2007
1 parent 28db6be commit 26ed687
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 32 deletions.
4 changes: 2 additions & 2 deletions drivers/infiniband/hw/ehca/ehca_classes.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ void ehca_cleanup_av_cache(void);
int ehca_init_mrmw_cache(void);
void ehca_cleanup_mrmw_cache(void);

extern spinlock_t ehca_qp_idr_lock;
extern spinlock_t ehca_cq_idr_lock;
extern rwlock_t ehca_qp_idr_lock;
extern rwlock_t ehca_cq_idr_lock;
extern struct idr ehca_qp_idr;
extern struct idr ehca_cq_idr;

Expand Down
12 changes: 6 additions & 6 deletions drivers/infiniband/hw/ehca/ehca_cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
goto create_cq_exit1;
}

spin_lock_irqsave(&ehca_cq_idr_lock, flags);
write_lock_irqsave(&ehca_cq_idr_lock, flags);
ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
write_unlock_irqrestore(&ehca_cq_idr_lock, flags);

} while (ret == -EAGAIN);

Expand Down Expand Up @@ -294,9 +294,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
"cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret);

create_cq_exit2:
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
write_lock_irqsave(&ehca_cq_idr_lock, flags);
idr_remove(&ehca_cq_idr, my_cq->token);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
write_unlock_irqrestore(&ehca_cq_idr_lock, flags);

create_cq_exit1:
kmem_cache_free(cq_cache, my_cq);
Expand Down Expand Up @@ -334,9 +334,9 @@ int ehca_destroy_cq(struct ib_cq *cq)
* remove the CQ from the idr first to make sure
* no more interrupt tasklets will touch this CQ
*/
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
write_lock_irqsave(&ehca_cq_idr_lock, flags);
idr_remove(&ehca_cq_idr, my_cq->token);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
write_unlock_irqrestore(&ehca_cq_idr_lock, flags);

/* now wait until all pending events have completed */
wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
Expand Down
19 changes: 8 additions & 11 deletions drivers/infiniband/hw/ehca/ehca_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,11 @@ static void qp_event_callback(struct ehca_shca *shca,
{
struct ib_event event;
struct ehca_qp *qp;
unsigned long flags;
u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);

spin_lock_irqsave(&ehca_qp_idr_lock, flags);
read_lock(&ehca_qp_idr_lock);
qp = idr_find(&ehca_qp_idr, token);
spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
read_unlock(&ehca_qp_idr_lock);


if (!qp)
Expand All @@ -209,14 +208,13 @@ static void cq_event_callback(struct ehca_shca *shca,
u64 eqe)
{
struct ehca_cq *cq;
unsigned long flags;
u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe);

spin_lock_irqsave(&ehca_cq_idr_lock, flags);
read_lock(&ehca_cq_idr_lock);
cq = idr_find(&ehca_cq_idr, token);
if (cq)
atomic_inc(&cq->nr_events);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
read_unlock(&ehca_cq_idr_lock);

if (!cq)
return;
Expand Down Expand Up @@ -411,19 +409,18 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
{
u64 eqe_value;
u32 token;
unsigned long flags;
struct ehca_cq *cq;

eqe_value = eqe->entry;
ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value);
if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
ehca_dbg(&shca->ib_device, "Got completion event");
token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
read_lock(&ehca_cq_idr_lock);
cq = idr_find(&ehca_cq_idr, token);
if (cq)
atomic_inc(&cq->nr_events);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
read_unlock(&ehca_cq_idr_lock);
if (cq == NULL) {
ehca_err(&shca->ib_device,
"Invalid eqe for non-existing cq token=%x",
Expand Down Expand Up @@ -480,11 +477,11 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
eqe_value = eqe_cache[eqe_cnt].eqe->entry;
if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
spin_lock(&ehca_cq_idr_lock);
read_lock(&ehca_cq_idr_lock);
eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
if (eqe_cache[eqe_cnt].cq)
atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
spin_unlock(&ehca_cq_idr_lock);
read_unlock(&ehca_cq_idr_lock);
if (!eqe_cache[eqe_cnt].cq) {
ehca_err(&shca->ib_device,
"Invalid eqe for non-existing cq "
Expand Down
4 changes: 2 additions & 2 deletions drivers/infiniband/hw/ehca/ehca_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ MODULE_PARM_DESC(static_rate,
MODULE_PARM_DESC(scaling_code,
"set scaling code (0: disabled/default, 1: enabled)");

DEFINE_SPINLOCK(ehca_qp_idr_lock);
DEFINE_SPINLOCK(ehca_cq_idr_lock);
DEFINE_RWLOCK(ehca_qp_idr_lock);
DEFINE_RWLOCK(ehca_cq_idr_lock);
DEFINE_IDR(ehca_qp_idr);
DEFINE_IDR(ehca_cq_idr);

Expand Down
12 changes: 6 additions & 6 deletions drivers/infiniband/hw/ehca/ehca_qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,9 +512,9 @@ struct ehca_qp *internal_create_qp(struct ib_pd *pd,
goto create_qp_exit0;
}

spin_lock_irqsave(&ehca_qp_idr_lock, flags);
write_lock_irqsave(&ehca_qp_idr_lock, flags);
ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);
spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
write_unlock_irqrestore(&ehca_qp_idr_lock, flags);

} while (ret == -EAGAIN);

Expand Down Expand Up @@ -733,9 +733,9 @@ struct ehca_qp *internal_create_qp(struct ib_pd *pd,
hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);

create_qp_exit1:
spin_lock_irqsave(&ehca_qp_idr_lock, flags);
write_lock_irqsave(&ehca_qp_idr_lock, flags);
idr_remove(&ehca_qp_idr, my_qp->token);
spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
write_unlock_irqrestore(&ehca_qp_idr_lock, flags);

create_qp_exit0:
kmem_cache_free(qp_cache, my_qp);
Expand Down Expand Up @@ -1706,9 +1706,9 @@ int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
}
}

spin_lock_irqsave(&ehca_qp_idr_lock, flags);
write_lock_irqsave(&ehca_qp_idr_lock, flags);
idr_remove(&ehca_qp_idr, my_qp->token);
spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
write_unlock_irqrestore(&ehca_qp_idr_lock, flags);

h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
if (h_ret != H_SUCCESS) {
Expand Down
9 changes: 4 additions & 5 deletions drivers/infiniband/hw/ehca/ehca_uverbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,17 +253,16 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
u32 cur_pid = current->tgid;
u32 ret;
unsigned long flags;
struct ehca_cq *cq;
struct ehca_qp *qp;
struct ehca_pd *pd;
struct ib_uobject *uobject;

switch (q_type) {
case 1: /* CQ */
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
read_lock(&ehca_cq_idr_lock);
cq = idr_find(&ehca_cq_idr, idr_handle);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
read_unlock(&ehca_cq_idr_lock);

/* make sure this mmap really belongs to the authorized user */
if (!cq)
Expand All @@ -289,9 +288,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
break;

case 2: /* QP */
spin_lock_irqsave(&ehca_qp_idr_lock, flags);
read_lock(&ehca_qp_idr_lock);
qp = idr_find(&ehca_qp_idr, idr_handle);
spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
read_unlock(&ehca_qp_idr_lock);

/* make sure this mmap really belongs to the authorized user */
if (!qp)
Expand Down

0 comments on commit 26ed687

Please sign in to comment.