aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r--drivers/infiniband/core/cm.c3
-rw-r--r--drivers/infiniband/core/fmr_pool.c38
-rw-r--r--drivers/infiniband/core/iwcm.c5
3 files changed, 27 insertions, 19 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index b10ade92efed..4df405157086 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3759,6 +3759,7 @@ static void cm_remove_one(struct ib_device *device)
3759 port = cm_dev->port[i-1]; 3759 port = cm_dev->port[i-1];
3760 ib_modify_port(device, port->port_num, 0, &port_modify); 3760 ib_modify_port(device, port->port_num, 0, &port_modify);
3761 ib_unregister_mad_agent(port->mad_agent); 3761 ib_unregister_mad_agent(port->mad_agent);
3762 flush_workqueue(cm.wq);
3762 cm_remove_port_fs(port); 3763 cm_remove_port_fs(port);
3763 } 3764 }
3764 kobject_put(&cm_dev->dev_obj); 3765 kobject_put(&cm_dev->dev_obj);
@@ -3813,6 +3814,7 @@ static void __exit ib_cm_cleanup(void)
3813 cancel_delayed_work(&timewait_info->work.work); 3814 cancel_delayed_work(&timewait_info->work.work);
3814 spin_unlock_irq(&cm.lock); 3815 spin_unlock_irq(&cm.lock);
3815 3816
3817 ib_unregister_client(&cm_client);
3816 destroy_workqueue(cm.wq); 3818 destroy_workqueue(cm.wq);
3817 3819
3818 list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) { 3820 list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
@@ -3820,7 +3822,6 @@ static void __exit ib_cm_cleanup(void)
3820 kfree(timewait_info); 3822 kfree(timewait_info);
3821 } 3823 }
3822 3824
3823 ib_unregister_client(&cm_client);
3824 class_unregister(&cm_class); 3825 class_unregister(&cm_class);
3825 idr_destroy(&cm.local_id_table); 3826 idr_destroy(&cm.local_id_table);
3826} 3827}
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 7f00347364f7..06d502c06a4d 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
139static void ib_fmr_batch_release(struct ib_fmr_pool *pool) 139static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
140{ 140{
141 int ret; 141 int ret;
142 struct ib_pool_fmr *fmr, *next; 142 struct ib_pool_fmr *fmr;
143 LIST_HEAD(unmap_list); 143 LIST_HEAD(unmap_list);
144 LIST_HEAD(fmr_list); 144 LIST_HEAD(fmr_list);
145 145
@@ -158,20 +158,6 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
158#endif 158#endif
159 } 159 }
160 160
161 /*
162 * The free_list may hold FMRs that have been put there
163 * because they haven't reached the max_remap count.
164 * Invalidate their mapping as well.
165 */
166 list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
167 if (fmr->remap_count == 0)
168 continue;
169 hlist_del_init(&fmr->cache_node);
170 fmr->remap_count = 0;
171 list_add_tail(&fmr->fmr->list, &fmr_list);
172 list_move(&fmr->list, &unmap_list);
173 }
174
175 list_splice(&pool->dirty_list, &unmap_list); 161 list_splice(&pool->dirty_list, &unmap_list);
176 INIT_LIST_HEAD(&pool->dirty_list); 162 INIT_LIST_HEAD(&pool->dirty_list);
177 pool->dirty_len = 0; 163 pool->dirty_len = 0;
@@ -384,6 +370,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
384 370
385 i = 0; 371 i = 0;
386 list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) { 372 list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
373 if (fmr->remap_count) {
374 INIT_LIST_HEAD(&fmr_list);
375 list_add_tail(&fmr->fmr->list, &fmr_list);
376 ib_unmap_fmr(&fmr_list);
377 }
387 ib_dealloc_fmr(fmr->fmr); 378 ib_dealloc_fmr(fmr->fmr);
388 list_del(&fmr->list); 379 list_del(&fmr->list);
389 kfree(fmr); 380 kfree(fmr);
@@ -407,8 +398,23 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
407 */ 398 */
408int ib_flush_fmr_pool(struct ib_fmr_pool *pool) 399int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
409{ 400{
410 int serial = atomic_inc_return(&pool->req_ser); 401 int serial;
402 struct ib_pool_fmr *fmr, *next;
403
404 /*
405 * The free_list holds FMRs that may have been used
406 * but have not been remapped enough times to be dirty.
407 * Put them on the dirty list now so that the cleanup
408 * thread will reap them too.
409 */
410 spin_lock_irq(&pool->pool_lock);
411 list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
412 if (fmr->remap_count > 0)
413 list_move(&fmr->list, &pool->dirty_list);
414 }
415 spin_unlock_irq(&pool->pool_lock);
411 416
417 serial = atomic_inc_return(&pool->req_ser);
412 wake_up_process(pool->thread); 418 wake_up_process(pool->thread);
413 419
414 if (wait_event_interruptible(pool->force_wait, 420 if (wait_event_interruptible(pool->force_wait,
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 223b1aa7d92b..81c9195b512a 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -839,6 +839,7 @@ static void cm_work_handler(struct work_struct *_work)
839 unsigned long flags; 839 unsigned long flags;
840 int empty; 840 int empty;
841 int ret = 0; 841 int ret = 0;
842 int destroy_id;
842 843
843 spin_lock_irqsave(&cm_id_priv->lock, flags); 844 spin_lock_irqsave(&cm_id_priv->lock, flags);
844 empty = list_empty(&cm_id_priv->work_list); 845 empty = list_empty(&cm_id_priv->work_list);
@@ -857,9 +858,9 @@ static void cm_work_handler(struct work_struct *_work)
857 destroy_cm_id(&cm_id_priv->id); 858 destroy_cm_id(&cm_id_priv->id);
858 } 859 }
859 BUG_ON(atomic_read(&cm_id_priv->refcount)==0); 860 BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
861 destroy_id = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
860 if (iwcm_deref_id(cm_id_priv)) { 862 if (iwcm_deref_id(cm_id_priv)) {
861 if (test_bit(IWCM_F_CALLBACK_DESTROY, 863 if (destroy_id) {
862 &cm_id_priv->flags)) {
863 BUG_ON(!list_empty(&cm_id_priv->work_list)); 864 BUG_ON(!list_empty(&cm_id_priv->work_list));
864 free_cm_id(cm_id_priv); 865 free_cm_id(cm_id_priv);
865 } 866 }