diff options
author | Mike Marciniszyn <mike.marciniszyn@qlogic.com> | 2011-12-23 08:03:41 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-01-03 23:53:31 -0500 |
commit | 489471095170ed1c6d0341739a243461638b0e06 (patch) | |
tree | d5820187d1d24dac7526bba2dd4dafb47c1bb0b3 /drivers/infiniband | |
parent | eddfb675256f49d14e8c5763098afe3eb2c93701 (diff) |
IB/qib: Optimize locking for get_txreq()
The current code locks the QP s_lock, followed by the pending_lock, I
guess to to protect against the allocate failing.
This patch only locks the pending_lock, assuming that the empty case
is an exeception, in which case the pending_lock is dropped, and the
original code is executed. This will save a lock of s_lock in the
normal case.
The observation is that the sdma descriptors will deplete at twice the
rate of txreq's, so this should be rare.
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@qlogic.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_verbs.c | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index a894762da462..7b6c3bffa9d9 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c | |||
@@ -913,8 +913,8 @@ static void copy_io(u32 __iomem *piobuf, struct qib_sge_state *ss, | |||
913 | __raw_writel(last, piobuf); | 913 | __raw_writel(last, piobuf); |
914 | } | 914 | } |
915 | 915 | ||
916 | static struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, | 916 | static noinline struct qib_verbs_txreq *__get_txreq(struct qib_ibdev *dev, |
917 | struct qib_qp *qp, int *retp) | 917 | struct qib_qp *qp) |
918 | { | 918 | { |
919 | struct qib_verbs_txreq *tx; | 919 | struct qib_verbs_txreq *tx; |
920 | unsigned long flags; | 920 | unsigned long flags; |
@@ -926,8 +926,9 @@ static struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, | |||
926 | struct list_head *l = dev->txreq_free.next; | 926 | struct list_head *l = dev->txreq_free.next; |
927 | 927 | ||
928 | list_del(l); | 928 | list_del(l); |
929 | spin_unlock(&dev->pending_lock); | ||
930 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
929 | tx = list_entry(l, struct qib_verbs_txreq, txreq.list); | 931 | tx = list_entry(l, struct qib_verbs_txreq, txreq.list); |
930 | *retp = 0; | ||
931 | } else { | 932 | } else { |
932 | if (ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK && | 933 | if (ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK && |
933 | list_empty(&qp->iowait)) { | 934 | list_empty(&qp->iowait)) { |
@@ -935,14 +936,33 @@ static struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, | |||
935 | qp->s_flags |= QIB_S_WAIT_TX; | 936 | qp->s_flags |= QIB_S_WAIT_TX; |
936 | list_add_tail(&qp->iowait, &dev->txwait); | 937 | list_add_tail(&qp->iowait, &dev->txwait); |
937 | } | 938 | } |
938 | tx = NULL; | ||
939 | qp->s_flags &= ~QIB_S_BUSY; | 939 | qp->s_flags &= ~QIB_S_BUSY; |
940 | *retp = -EBUSY; | 940 | spin_unlock(&dev->pending_lock); |
941 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
942 | tx = ERR_PTR(-EBUSY); | ||
941 | } | 943 | } |
944 | return tx; | ||
945 | } | ||
942 | 946 | ||
943 | spin_unlock(&dev->pending_lock); | 947 | static inline struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, |
944 | spin_unlock_irqrestore(&qp->s_lock, flags); | 948 | struct qib_qp *qp) |
949 | { | ||
950 | struct qib_verbs_txreq *tx; | ||
951 | unsigned long flags; | ||
945 | 952 | ||
953 | spin_lock_irqsave(&dev->pending_lock, flags); | ||
954 | /* assume the list non empty */ | ||
955 | if (likely(!list_empty(&dev->txreq_free))) { | ||
956 | struct list_head *l = dev->txreq_free.next; | ||
957 | |||
958 | list_del(l); | ||
959 | spin_unlock_irqrestore(&dev->pending_lock, flags); | ||
960 | tx = list_entry(l, struct qib_verbs_txreq, txreq.list); | ||
961 | } else { | ||
962 | /* call slow path to get the extra lock */ | ||
963 | spin_unlock_irqrestore(&dev->pending_lock, flags); | ||
964 | tx = __get_txreq(dev, qp); | ||
965 | } | ||
946 | return tx; | 966 | return tx; |
947 | } | 967 | } |
948 | 968 | ||
@@ -1122,9 +1142,9 @@ static int qib_verbs_send_dma(struct qib_qp *qp, struct qib_ib_header *hdr, | |||
1122 | goto bail; | 1142 | goto bail; |
1123 | } | 1143 | } |
1124 | 1144 | ||
1125 | tx = get_txreq(dev, qp, &ret); | 1145 | tx = get_txreq(dev, qp); |
1126 | if (!tx) | 1146 | if (IS_ERR(tx)) |
1127 | goto bail; | 1147 | goto bail_tx; |
1128 | 1148 | ||
1129 | control = dd->f_setpbc_control(ppd, plen, qp->s_srate, | 1149 | control = dd->f_setpbc_control(ppd, plen, qp->s_srate, |
1130 | be16_to_cpu(hdr->lrh[0]) >> 12); | 1150 | be16_to_cpu(hdr->lrh[0]) >> 12); |
@@ -1195,6 +1215,9 @@ unaligned: | |||
1195 | ibp->n_unaligned++; | 1215 | ibp->n_unaligned++; |
1196 | bail: | 1216 | bail: |
1197 | return ret; | 1217 | return ret; |
1218 | bail_tx: | ||
1219 | ret = PTR_ERR(tx); | ||
1220 | goto bail; | ||
1198 | } | 1221 | } |
1199 | 1222 | ||
1200 | /* | 1223 | /* |