diff options
author | Alexander Schmidt <alexs@linux.vnet.ibm.com> | 2009-12-09 13:11:04 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-12-09 13:11:04 -0500 |
commit | 9420269428b3dc80c98e52beac60a3976fbef7d2 (patch) | |
tree | b2b43bbaa396613434143efe79b00b15eed690f1 /drivers/infiniband | |
parent | 91d3f9bacdb4950d2f79fe2ba296aa249f60d06c (diff) |
IB/ehca: Rework destroy_eq()
The ibmebus_free_irq() function, which might sleep, was called with
interrupts disabled. To fix this, make sure that no interrupts are
running by killing the interrupt tasklet. Also lock the
shca_list_lock to protect against the poll_eqs_timer running
concurrently.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_eq.c | 9 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 2 |
3 files changed, 8 insertions, 4 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index c825142a2fb7..0136abd50dd4 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -375,6 +375,7 @@ extern rwlock_t ehca_qp_idr_lock; | |||
375 | extern rwlock_t ehca_cq_idr_lock; | 375 | extern rwlock_t ehca_cq_idr_lock; |
376 | extern struct idr ehca_qp_idr; | 376 | extern struct idr ehca_qp_idr; |
377 | extern struct idr ehca_cq_idr; | 377 | extern struct idr ehca_cq_idr; |
378 | extern spinlock_t shca_list_lock; | ||
378 | 379 | ||
379 | extern int ehca_static_rate; | 380 | extern int ehca_static_rate; |
380 | extern int ehca_port_act_time; | 381 | extern int ehca_port_act_time; |
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c index 523e733c630e..3b87589b8ea0 100644 --- a/drivers/infiniband/hw/ehca/ehca_eq.c +++ b/drivers/infiniband/hw/ehca/ehca_eq.c | |||
@@ -169,12 +169,15 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq) | |||
169 | unsigned long flags; | 169 | unsigned long flags; |
170 | u64 h_ret; | 170 | u64 h_ret; |
171 | 171 | ||
172 | spin_lock_irqsave(&eq->spinlock, flags); | ||
173 | ibmebus_free_irq(eq->ist, (void *)shca); | 172 | ibmebus_free_irq(eq->ist, (void *)shca); |
174 | 173 | ||
175 | h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); | 174 | spin_lock_irqsave(&shca_list_lock, flags); |
175 | eq->is_initialized = 0; | ||
176 | spin_unlock_irqrestore(&shca_list_lock, flags); | ||
176 | 177 | ||
177 | spin_unlock_irqrestore(&eq->spinlock, flags); | 178 | tasklet_kill(&eq->interrupt_task); |
179 | |||
180 | h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); | ||
178 | 181 | ||
179 | if (h_ret != H_SUCCESS) { | 182 | if (h_ret != H_SUCCESS) { |
180 | ehca_err(&shca->ib_device, "Can't free EQ resources."); | 183 | ehca_err(&shca->ib_device, "Can't free EQ resources."); |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index fb2d83c5bf01..129a6bebd6e3 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -123,7 +123,7 @@ DEFINE_IDR(ehca_qp_idr); | |||
123 | DEFINE_IDR(ehca_cq_idr); | 123 | DEFINE_IDR(ehca_cq_idr); |
124 | 124 | ||
125 | static LIST_HEAD(shca_list); /* list of all registered ehcas */ | 125 | static LIST_HEAD(shca_list); /* list of all registered ehcas */ |
126 | static DEFINE_SPINLOCK(shca_list_lock); | 126 | DEFINE_SPINLOCK(shca_list_lock); |
127 | 127 | ||
128 | static struct timer_list poll_eqs_timer; | 128 | static struct timer_list poll_eqs_timer; |
129 | 129 | ||