From: Eldad Zinger Date: Sun, 4 Jul 2010 13:30:43 +0000 (+0300) Subject: sdp: device_removal_lock should not be a spinlock because module removal takes a... X-Git-Tag: v4.1.12-92~264^2~5^2~152 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=d88b3468e769df80bea2425d10687a37cd36a6f9;p=users%2Fjedix%2Flinux-maple.git sdp: device_removal_lock should not be a spinlock because module removal takes a long time. In order to prevent a situation that many CPUs are stack with read-spinlock waiting for remove-device write-lock to be freed, I replaced the rw-spinlock with rw-semaphore. That way the blocked processes goes to sleep and are not blocking other processes. Signed-off-by: Eldad Zinger --- diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h index fd98ca905024b..0f6babb033bda 100644 --- a/drivers/infiniband/ulp/sdp/sdp.h +++ b/drivers/infiniband/ulp/sdp/sdp.h @@ -3,6 +3,7 @@ #include #include +#include #include #include /* For urgent data flags */ #include @@ -800,7 +801,7 @@ void sdp_reset_sk(struct sock *sk, int rc); void sdp_reset(struct sock *sk); int sdp_tx_wait_memory(struct sdp_sock *ssk, long *timeo_p, int *credits_needed); void sdp_skb_entail(struct sock *sk, struct sk_buff *skb); -extern rwlock_t device_removal_lock; +extern struct rw_semaphore device_removal_lock; /* sdp_proc.c */ int __init sdp_proc_init(void); diff --git a/drivers/infiniband/ulp/sdp/sdp_cma.c b/drivers/infiniband/ulp/sdp/sdp_cma.c index a940579783180..35532ad00c8c8 100644 --- a/drivers/infiniband/ulp/sdp/sdp_cma.c +++ b/drivers/infiniband/ulp/sdp/sdp_cma.c @@ -175,18 +175,18 @@ static int sdp_connect_handler(struct sock *sk, struct rdma_cm_id *id, bh_unlock_sock(child); __sock_put(child, SOCK_REF_CLONE); - read_lock(&device_removal_lock); + down_read(&device_removal_lock); rc = sdp_init_qp(child, id); if (rc) { - read_unlock(&device_removal_lock); + up_read(&device_removal_lock); sdp_sk(child)->destructed_already = 1; sk_free(child); return rc; } sdp_add_sock(sdp_sk(child)); - read_unlock(&device_removal_lock); + up_read(&device_removal_lock); sdp_sk(child)->max_bufs = ntohs(h->bsdh.bufs); atomic_set(&sdp_sk(child)->tx_ring.credits, sdp_sk(child)->max_bufs); diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index 9acff248984eb..7c8494c3deb45 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -119,7 +119,7 @@ struct workqueue_struct *rx_comp_wq; struct list_head sock_list; spinlock_t sock_list_lock; -DEFINE_RWLOCK(device_removal_lock); +DECLARE_RWSEM(device_removal_lock); static inline unsigned int sdp_keepalive_time_when(const struct sdp_sock *ssk) { @@ -521,10 +521,10 @@ static void sdp_destruct(struct sock *sk) ssk->destructed_already = 1; - read_lock(&device_removal_lock); + down_read(&device_removal_lock); sdp_remove_sock(ssk); sdp_destroy_resources(sk); - read_unlock(&device_removal_lock); + up_read(&device_removal_lock); flush_scheduled_work(); @@ -2810,7 +2810,7 @@ static void sdp_remove_device(struct ib_device *device) /* destroy_ids: */ do_next: - write_lock(&device_removal_lock); + down_write(&device_removal_lock); spin_lock_irq(&sock_list_lock); list_for_each_entry(ssk, &sock_list, sock_list) { @@ -2825,7 +2825,7 @@ do_next: ssk->id_destroyed_already = 1; release_sock(sk); - write_unlock(&device_removal_lock); + up_write(&device_removal_lock); if (id) rdma_destroy_id(id); @@ -2859,7 +2859,7 @@ kill_socks: spin_unlock_irq(&sock_list_lock); - write_unlock(&device_removal_lock); + up_write(&device_removal_lock); if (!sdp_dev) return;