aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart Van Assche <bart.vanassche@sandisk.com>2016-02-11 14:08:34 -0500
committerDoug Ledford <dledford@redhat.com>2016-02-29 17:12:36 -0500
commit8628991fbe6a9086189f55f0b33dee7f25108ecc (patch)
tree4cfe8e1c7373c8a93c1d68de0a3b815d98c86240
parentc13c90ea6762d834a07c0aa18134d98794f6fc3d (diff)
IB/srpt: Use a mutex to protect the channel list
In a later patch a function that can block will be called while iterating over the rch_list. Hence protect that list with a mutex instead of a spinlock. And since it is not allowed to sleep while the task state != TASK_RUNNING, convert the list test in srpt_ch_list_empty() into a lockless test. Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Cc: Sagi Grimberg <sagig@mellanox.com> Cc: Alex Estrin <alex.estrin@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c42
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.h4
2 files changed, 17 insertions, 29 deletions
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 0bf204ec443e..33bd408c5eea 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -1862,12 +1862,11 @@ static void __srpt_close_ch(struct srpt_rdma_ch *ch)
1862 */ 1862 */
1863static void srpt_close_ch(struct srpt_rdma_ch *ch) 1863static void srpt_close_ch(struct srpt_rdma_ch *ch)
1864{ 1864{
1865 struct srpt_device *sdev; 1865 struct srpt_device *sdev = ch->sport->sdev;
1866 1866
1867 sdev = ch->sport->sdev; 1867 mutex_lock(&sdev->mutex);
1868 spin_lock_irq(&sdev->spinlock);
1869 __srpt_close_ch(ch); 1868 __srpt_close_ch(ch);
1870 spin_unlock_irq(&sdev->spinlock); 1869 mutex_unlock(&sdev->mutex);
1871} 1870}
1872 1871
1873/** 1872/**
@@ -1954,11 +1953,11 @@ static void srpt_release_channel_work(struct work_struct *w)
1954 ch->sport->sdev, ch->rq_size, 1953 ch->sport->sdev, ch->rq_size,
1955 ch->rsp_size, DMA_TO_DEVICE); 1954 ch->rsp_size, DMA_TO_DEVICE);
1956 1955
1957 spin_lock_irq(&sdev->spinlock); 1956 mutex_lock(&sdev->mutex);
1958 list_del_init(&ch->list); 1957 list_del_init(&ch->list);
1959 if (ch->release_done) 1958 if (ch->release_done)
1960 complete(ch->release_done); 1959 complete(ch->release_done);
1961 spin_unlock_irq(&sdev->spinlock); 1960 mutex_unlock(&sdev->mutex);
1962 1961
1963 wake_up(&sdev->ch_releaseQ); 1962 wake_up(&sdev->ch_releaseQ);
1964 1963
@@ -2039,7 +2038,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
2039 if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) { 2038 if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
2040 rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN; 2039 rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
2041 2040
2042 spin_lock_irq(&sdev->spinlock); 2041 mutex_lock(&sdev->mutex);
2043 2042
2044 list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) { 2043 list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) {
2045 if (!memcmp(ch->i_port_id, req->initiator_port_id, 16) 2044 if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)
@@ -2063,7 +2062,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
2063 } 2062 }
2064 } 2063 }
2065 2064
2066 spin_unlock_irq(&sdev->spinlock); 2065 mutex_unlock(&sdev->mutex);
2067 2066
2068 } else 2067 } else
2069 rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED; 2068 rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
@@ -2208,9 +2207,9 @@ try_again:
2208 goto release_channel; 2207 goto release_channel;
2209 } 2208 }
2210 2209
2211 spin_lock_irq(&sdev->spinlock); 2210 mutex_lock(&sdev->mutex);
2212 list_add_tail(&ch->list, &sdev->rch_list); 2211 list_add_tail(&ch->list, &sdev->rch_list);
2213 spin_unlock_irq(&sdev->spinlock); 2212 mutex_unlock(&sdev->mutex);
2214 2213
2215 goto out; 2214 goto out;
2216 2215
@@ -2653,17 +2652,6 @@ static void srpt_refresh_port_work(struct work_struct *work)
2653 srpt_refresh_port(sport); 2652 srpt_refresh_port(sport);
2654} 2653}
2655 2654
2656static int srpt_ch_list_empty(struct srpt_device *sdev)
2657{
2658 int res;
2659
2660 spin_lock_irq(&sdev->spinlock);
2661 res = list_empty(&sdev->rch_list);
2662 spin_unlock_irq(&sdev->spinlock);
2663
2664 return res;
2665}
2666
2667/** 2655/**
2668 * srpt_release_sdev() - Free the channel resources associated with a target. 2656 * srpt_release_sdev() - Free the channel resources associated with a target.
2669 */ 2657 */
@@ -2676,13 +2664,13 @@ static int srpt_release_sdev(struct srpt_device *sdev)
2676 2664
2677 BUG_ON(!sdev); 2665 BUG_ON(!sdev);
2678 2666
2679 spin_lock_irq(&sdev->spinlock); 2667 mutex_lock(&sdev->mutex);
2680 list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) 2668 list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list)
2681 __srpt_close_ch(ch); 2669 __srpt_close_ch(ch);
2682 spin_unlock_irq(&sdev->spinlock); 2670 mutex_unlock(&sdev->mutex);
2683 2671
2684 res = wait_event_interruptible(sdev->ch_releaseQ, 2672 res = wait_event_interruptible(sdev->ch_releaseQ,
2685 srpt_ch_list_empty(sdev)); 2673 list_empty_careful(&sdev->rch_list));
2686 if (res) 2674 if (res)
2687 pr_err("%s: interrupted.\n", __func__); 2675 pr_err("%s: interrupted.\n", __func__);
2688 2676
@@ -2743,7 +2731,7 @@ static void srpt_add_one(struct ib_device *device)
2743 sdev->device = device; 2731 sdev->device = device;
2744 INIT_LIST_HEAD(&sdev->rch_list); 2732 INIT_LIST_HEAD(&sdev->rch_list);
2745 init_waitqueue_head(&sdev->ch_releaseQ); 2733 init_waitqueue_head(&sdev->ch_releaseQ);
2746 spin_lock_init(&sdev->spinlock); 2734 mutex_init(&sdev->mutex);
2747 2735
2748 sdev->pd = ib_alloc_pd(device); 2736 sdev->pd = ib_alloc_pd(device);
2749 if (IS_ERR(sdev->pd)) 2737 if (IS_ERR(sdev->pd))
@@ -2971,12 +2959,12 @@ static void srpt_close_session(struct se_session *se_sess)
2971 pr_debug("ch %s-%d state %d\n", ch->sess_name, ch->qp->qp_num, 2959 pr_debug("ch %s-%d state %d\n", ch->sess_name, ch->qp->qp_num,
2972 ch->state); 2960 ch->state);
2973 2961
2974 spin_lock_irq(&sdev->spinlock); 2962 mutex_lock(&sdev->mutex);
2975 BUG_ON(ch->release_done); 2963 BUG_ON(ch->release_done);
2976 ch->release_done = &release_done; 2964 ch->release_done = &release_done;
2977 wait = !list_empty(&ch->list); 2965 wait = !list_empty(&ch->list);
2978 __srpt_close_ch(ch); 2966 __srpt_close_ch(ch);
2979 spin_unlock_irq(&sdev->spinlock); 2967 mutex_unlock(&sdev->mutex);
2980 2968
2981 if (!wait) 2969 if (!wait)
2982 return; 2970 return;
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
index 9c326c71607c..5883295a7b97 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.h
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.h
@@ -342,7 +342,7 @@ struct srpt_port {
342 * @ioctx_ring: Per-HCA SRQ. 342 * @ioctx_ring: Per-HCA SRQ.
343 * @rch_list: Per-device channel list -- see also srpt_rdma_ch.list. 343 * @rch_list: Per-device channel list -- see also srpt_rdma_ch.list.
344 * @ch_releaseQ: Enables waiting for removal from rch_list. 344 * @ch_releaseQ: Enables waiting for removal from rch_list.
345 * @spinlock: Protects rch_list and tpg. 345 * @mutex: Protects rch_list.
346 * @port: Information about the ports owned by this HCA. 346 * @port: Information about the ports owned by this HCA.
347 * @event_handler: Per-HCA asynchronous IB event handler. 347 * @event_handler: Per-HCA asynchronous IB event handler.
348 * @list: Node in srpt_dev_list. 348 * @list: Node in srpt_dev_list.
@@ -356,7 +356,7 @@ struct srpt_device {
356 struct srpt_recv_ioctx **ioctx_ring; 356 struct srpt_recv_ioctx **ioctx_ring;
357 struct list_head rch_list; 357 struct list_head rch_list;
358 wait_queue_head_t ch_releaseQ; 358 wait_queue_head_t ch_releaseQ;
359 spinlock_t spinlock; 359 struct mutex mutex;
360 struct srpt_port port[2]; 360 struct srpt_port port[2];
361 struct ib_event_handler event_handler; 361 struct ib_event_handler event_handler;
362 struct list_head list; 362 struct list_head list;