IB/rdmavt: Setting of QP timeout can overflow jiffies computation
authorKaike Wan <kaike.wan@intel.com>
Sat, 17 Jun 2017 17:37:26 +0000 (10:37 -0700)
committerDoug Ledford <dledford@redhat.com>
Thu, 20 Jul 2017 15:20:50 +0000 (11:20 -0400)
Current computation of qp->timeout_jiffies in rvt_modify_qp() will cause
overflow due to the fact that the input to the function usecs_to_jiffies
is only 32-bit ( unsigned int). Overflow will occur when attr->timeout is
equal to or greater than 30. The consequence is unnecessarily excessive
retry and thus degradation of the system performance.

This patch fixes the problem by limiting the input to 5-bit and calling
usecs_to_jiffies() before multiplying the scaling factor.

Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Kaike Wan <kaike.wan@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/sw/rdmavt/qp.c
include/rdma/rdmavt_qp.h

index 459865439a0bf50affcd8300237e135fb03e9faa..8876ee7bc326c9d5a05f438830ec1ba0740eebef 100644 (file)
@@ -1258,9 +1258,7 @@ int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 
        if (attr_mask & IB_QP_TIMEOUT) {
                qp->timeout = attr->timeout;
-               qp->timeout_jiffies =
-                       usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
-                               1000UL);
+               qp->timeout_jiffies = rvt_timeout_to_jiffies(qp->timeout);
        }
 
        if (attr_mask & IB_QP_QKEY)
index be6472e5b06bd1ed1117e928e9b3d44748dfbfeb..d664d2e762808321d7b2aece6d3146b713b51631 100644 (file)
@@ -647,6 +647,20 @@ static inline u32 rvt_div_mtu(struct rvt_qp *qp, u32 len)
        return len >> qp->log_pmtu;
 }
 
+/**
+ * rvt_timeout_to_jiffies - Convert a ULP timeout input into jiffies
+ * @timeout - timeout input(0 - 31).
+ *
+ * Return a timeout value in jiffies.
+ */
+static inline unsigned long rvt_timeout_to_jiffies(u8 timeout)
+{
+       if (timeout > 31)
+               timeout = 31;
+
+       return usecs_to_jiffies(1U << timeout) * 4096UL / 1000UL;
+}
+
 extern const int  ib_rvt_state_ops[];
 
 struct rvt_dev_info;