diff options
author | Venkata Sandeep Dhanalakota <venkata.s.dhanalakota@intel.com> | 2017-02-08 08:27:13 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2017-02-19 09:18:39 -0500 |
commit | 11a10d4bc7b2640da1fce27586a617411b70f5c5 (patch) | |
tree | 84f603df164089c5b3dd069b14ad74551d6de101 | |
parent | 696513e8cf39ccb8ee8010fd2157f095b3af6a91 (diff) |
IB/rdmavt: Adding timer logic to rdmavt
To move common code across target to rdmavt for code reuse.
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: Brian Welty <brian.welty@intel.com>
Signed-off-by: Venkata Sandeep Dhanalakota <venkata.s.dhanalakota@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/sw/rdmavt/qp.c | 183 | ||||
-rw-r--r-- | include/rdma/rdma_vt.h | 19 | ||||
-rw-r--r-- | include/rdma/rdmavt_qp.h | 6 |
3 files changed, 206 insertions, 2 deletions
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 444b06cada22..db4315f8f0c8 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c | |||
@@ -55,6 +55,46 @@ | |||
55 | #include "vt.h" | 55 | #include "vt.h" |
56 | #include "trace.h" | 56 | #include "trace.h" |
57 | 57 | ||
58 | static void rvt_rc_timeout(unsigned long arg); | ||
59 | |||
60 | /* | ||
61 | * Convert the AETH RNR timeout code into the number of microseconds. | ||
62 | */ | ||
63 | static const u32 ib_rvt_rnr_table[32] = { | ||
64 | 655360, /* 00: 655.36 */ | ||
65 | 10, /* 01: .01 */ | ||
66 | 20, /* 02 .02 */ | ||
67 | 30, /* 03: .03 */ | ||
68 | 40, /* 04: .04 */ | ||
69 | 60, /* 05: .06 */ | ||
70 | 80, /* 06: .08 */ | ||
71 | 120, /* 07: .12 */ | ||
72 | 160, /* 08: .16 */ | ||
73 | 240, /* 09: .24 */ | ||
74 | 320, /* 0A: .32 */ | ||
75 | 480, /* 0B: .48 */ | ||
76 | 640, /* 0C: .64 */ | ||
77 | 960, /* 0D: .96 */ | ||
78 | 1280, /* 0E: 1.28 */ | ||
79 | 1920, /* 0F: 1.92 */ | ||
80 | 2560, /* 10: 2.56 */ | ||
81 | 3840, /* 11: 3.84 */ | ||
82 | 5120, /* 12: 5.12 */ | ||
83 | 7680, /* 13: 7.68 */ | ||
84 | 10240, /* 14: 10.24 */ | ||
85 | 15360, /* 15: 15.36 */ | ||
86 | 20480, /* 16: 20.48 */ | ||
87 | 30720, /* 17: 30.72 */ | ||
88 | 40960, /* 18: 40.96 */ | ||
89 | 61440, /* 19: 61.44 */ | ||
90 | 81920, /* 1A: 81.92 */ | ||
91 | 122880, /* 1B: 122.88 */ | ||
92 | 163840, /* 1C: 163.84 */ | ||
93 | 245760, /* 1D: 245.76 */ | ||
94 | 327680, /* 1E: 327.68 */ | ||
95 | 491520 /* 1F: 491.52 */ | ||
96 | }; | ||
97 | |||
58 | /* | 98 | /* |
59 | * Note that it is OK to post send work requests in the SQE and ERR | 99 | * Note that it is OK to post send work requests in the SQE and ERR |
60 | * states; rvt_do_send() will process them and generate error | 100 | * states; rvt_do_send() will process them and generate error |
@@ -200,7 +240,8 @@ int rvt_driver_qp_init(struct rvt_dev_info *rdi) | |||
200 | if (!rdi->driver_f.free_all_qps || | 240 | if (!rdi->driver_f.free_all_qps || |
201 | !rdi->driver_f.qp_priv_alloc || | 241 | !rdi->driver_f.qp_priv_alloc || |
202 | !rdi->driver_f.qp_priv_free || | 242 | !rdi->driver_f.qp_priv_free || |
203 | !rdi->driver_f.notify_qp_reset) | 243 | !rdi->driver_f.notify_qp_reset || |
244 | !rdi->driver_f.notify_restart_rc) | ||
204 | return -EINVAL; | 245 | return -EINVAL; |
205 | 246 | ||
206 | /* allocate parent object */ | 247 | /* allocate parent object */ |
@@ -587,6 +628,7 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, | |||
587 | 628 | ||
588 | /* Let drivers flush their waitlist */ | 629 | /* Let drivers flush their waitlist */ |
589 | rdi->driver_f.flush_qp_waiters(qp); | 630 | rdi->driver_f.flush_qp_waiters(qp); |
631 | rvt_stop_rc_timers(qp); | ||
590 | qp->s_flags &= ~(RVT_S_TIMER | RVT_S_ANY_WAIT); | 632 | qp->s_flags &= ~(RVT_S_TIMER | RVT_S_ANY_WAIT); |
591 | spin_unlock(&qp->s_lock); | 633 | spin_unlock(&qp->s_lock); |
592 | spin_unlock(&qp->s_hlock); | 634 | spin_unlock(&qp->s_hlock); |
@@ -594,7 +636,7 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, | |||
594 | 636 | ||
595 | /* Stop the send queue and the retry timer */ | 637 | /* Stop the send queue and the retry timer */ |
596 | rdi->driver_f.stop_send_queue(qp); | 638 | rdi->driver_f.stop_send_queue(qp); |
597 | 639 | rvt_del_timers_sync(qp); | |
598 | /* Wait for things to stop */ | 640 | /* Wait for things to stop */ |
599 | rdi->driver_f.quiesce_qp(qp); | 641 | rdi->driver_f.quiesce_qp(qp); |
600 | 642 | ||
@@ -730,6 +772,11 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, | |||
730 | if (!qp->s_ack_queue) | 772 | if (!qp->s_ack_queue) |
731 | goto bail_qp; | 773 | goto bail_qp; |
732 | } | 774 | } |
775 | /* initialize timers needed for rc qp */ | ||
776 | setup_timer(&qp->s_timer, rvt_rc_timeout, (unsigned long)qp); | ||
777 | hrtimer_init(&qp->s_rnr_timer, CLOCK_MONOTONIC, | ||
778 | HRTIMER_MODE_REL); | ||
779 | qp->s_rnr_timer.function = rvt_rc_rnr_retry; | ||
733 | 780 | ||
734 | /* | 781 | /* |
735 | * Driver needs to set up it's private QP structure and do any | 782 | * Driver needs to set up it's private QP structure and do any |
@@ -1906,3 +1953,135 @@ void rvt_rc_error(struct rvt_qp *qp, enum ib_wc_status err) | |||
1906 | } | 1953 | } |
1907 | } | 1954 | } |
1908 | EXPORT_SYMBOL(rvt_rc_error); | 1955 | EXPORT_SYMBOL(rvt_rc_error); |
1956 | |||
1957 | static inline unsigned long rvt_aeth_to_usec(u32 aeth) | ||
1958 | { | ||
1959 | return ib_rvt_rnr_table[(aeth >> RVT_AETH_CREDIT_SHIFT) & | ||
1960 | RVT_AETH_CREDIT_MASK]; | ||
1961 | } | ||
1962 | |||
1963 | /* | ||
1964 | * rvt_add_retry_timer - add/start a retry timer | ||
1965 | * @qp - the QP | ||
1966 | * add a retry timer on the QP | ||
1967 | */ | ||
1968 | void rvt_add_retry_timer(struct rvt_qp *qp) | ||
1969 | { | ||
1970 | struct ib_qp *ibqp = &qp->ibqp; | ||
1971 | struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device); | ||
1972 | |||
1973 | lockdep_assert_held(&qp->s_lock); | ||
1974 | qp->s_flags |= RVT_S_TIMER; | ||
1975 | /* 4.096 usec. * (1 << qp->timeout) */ | ||
1976 | qp->s_timer.expires = jiffies + qp->timeout_jiffies + | ||
1977 | rdi->busy_jiffies; | ||
1978 | add_timer(&qp->s_timer); | ||
1979 | } | ||
1980 | EXPORT_SYMBOL(rvt_add_retry_timer); | ||
1981 | |||
1982 | /** | ||
1983 | * rvt_add_rnr_timer - add/start an rnr timer | ||
1984 | * @qp - the QP | ||
1985 | * @aeth - aeth of RNR timeout, simulated aeth for loopback | ||
1986 | * add an rnr timer on the QP | ||
1987 | */ | ||
1988 | void rvt_add_rnr_timer(struct rvt_qp *qp, u32 aeth) | ||
1989 | { | ||
1990 | u32 to; | ||
1991 | |||
1992 | lockdep_assert_held(&qp->s_lock); | ||
1993 | qp->s_flags |= RVT_S_WAIT_RNR; | ||
1994 | to = rvt_aeth_to_usec(aeth); | ||
1995 | hrtimer_start(&qp->s_rnr_timer, | ||
1996 | ns_to_ktime(1000 * to), HRTIMER_MODE_REL); | ||
1997 | } | ||
1998 | EXPORT_SYMBOL(rvt_add_rnr_timer); | ||
1999 | |||
2000 | /** | ||
2001 | * rvt_stop_rc_timers - stop all timers | ||
2002 | * @qp - the QP | ||
2003 | * stop any pending timers | ||
2004 | */ | ||
2005 | void rvt_stop_rc_timers(struct rvt_qp *qp) | ||
2006 | { | ||
2007 | lockdep_assert_held(&qp->s_lock); | ||
2008 | /* Remove QP from all timers */ | ||
2009 | if (qp->s_flags & (RVT_S_TIMER | RVT_S_WAIT_RNR)) { | ||
2010 | qp->s_flags &= ~(RVT_S_TIMER | RVT_S_WAIT_RNR); | ||
2011 | del_timer(&qp->s_timer); | ||
2012 | hrtimer_try_to_cancel(&qp->s_rnr_timer); | ||
2013 | } | ||
2014 | } | ||
2015 | EXPORT_SYMBOL(rvt_stop_rc_timers); | ||
2016 | |||
2017 | /** | ||
2018 | * rvt_stop_rnr_timer - stop an rnr timer | ||
2019 | * @qp - the QP | ||
2020 | * | ||
2021 | * stop an rnr timer and return if the timer | ||
2022 | * had been pending. | ||
2023 | */ | ||
2024 | static int rvt_stop_rnr_timer(struct rvt_qp *qp) | ||
2025 | { | ||
2026 | int rval = 0; | ||
2027 | |||
2028 | lockdep_assert_held(&qp->s_lock); | ||
2029 | /* Remove QP from rnr timer */ | ||
2030 | if (qp->s_flags & RVT_S_WAIT_RNR) { | ||
2031 | qp->s_flags &= ~RVT_S_WAIT_RNR; | ||
2032 | rval = hrtimer_try_to_cancel(&qp->s_rnr_timer); | ||
2033 | } | ||
2034 | return rval; | ||
2035 | } | ||
2036 | |||
2037 | /** | ||
2038 | * rvt_del_timers_sync - wait for any timeout routines to exit | ||
2039 | * @qp - the QP | ||
2040 | */ | ||
2041 | void rvt_del_timers_sync(struct rvt_qp *qp) | ||
2042 | { | ||
2043 | del_timer_sync(&qp->s_timer); | ||
2044 | hrtimer_cancel(&qp->s_rnr_timer); | ||
2045 | } | ||
2046 | EXPORT_SYMBOL(rvt_del_timers_sync); | ||
2047 | |||
2048 | /** | ||
2049 | * This is called from s_timer for missing responses. | ||
2050 | */ | ||
2051 | static void rvt_rc_timeout(unsigned long arg) | ||
2052 | { | ||
2053 | struct rvt_qp *qp = (struct rvt_qp *)arg; | ||
2054 | struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device); | ||
2055 | unsigned long flags; | ||
2056 | |||
2057 | spin_lock_irqsave(&qp->r_lock, flags); | ||
2058 | spin_lock(&qp->s_lock); | ||
2059 | if (qp->s_flags & RVT_S_TIMER) { | ||
2060 | qp->s_flags &= ~RVT_S_TIMER; | ||
2061 | del_timer(&qp->s_timer); | ||
2062 | if (rdi->driver_f.notify_restart_rc) | ||
2063 | rdi->driver_f.notify_restart_rc(qp, | ||
2064 | qp->s_last_psn + 1, | ||
2065 | 1); | ||
2066 | rdi->driver_f.schedule_send(qp); | ||
2067 | } | ||
2068 | spin_unlock(&qp->s_lock); | ||
2069 | spin_unlock_irqrestore(&qp->r_lock, flags); | ||
2070 | } | ||
2071 | |||
2072 | /* | ||
2073 | * This is called from s_timer for RNR timeouts. | ||
2074 | */ | ||
2075 | enum hrtimer_restart rvt_rc_rnr_retry(struct hrtimer *t) | ||
2076 | { | ||
2077 | struct rvt_qp *qp = container_of(t, struct rvt_qp, s_rnr_timer); | ||
2078 | struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device); | ||
2079 | unsigned long flags; | ||
2080 | |||
2081 | spin_lock_irqsave(&qp->s_lock, flags); | ||
2082 | rvt_stop_rnr_timer(qp); | ||
2083 | rdi->driver_f.schedule_send(qp); | ||
2084 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
2085 | return HRTIMER_NORESTART; | ||
2086 | } | ||
2087 | EXPORT_SYMBOL(rvt_rc_rnr_retry); | ||
diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h index 861e23eaebda..a69dee38365f 100644 --- a/include/rdma/rdma_vt.h +++ b/include/rdma/rdma_vt.h | |||
@@ -335,6 +335,8 @@ struct rvt_driver_provided { | |||
335 | /* Notify driver a mad agent has been removed */ | 335 | /* Notify driver a mad agent has been removed */ |
336 | void (*notify_free_mad_agent)(struct rvt_dev_info *rdi, int port_idx); | 336 | void (*notify_free_mad_agent)(struct rvt_dev_info *rdi, int port_idx); |
337 | 337 | ||
338 | /* Notify driver to restart rc */ | ||
339 | void (*notify_restart_rc)(struct rvt_qp *qp, u32 psn, int wait); | ||
338 | }; | 340 | }; |
339 | 341 | ||
340 | struct rvt_dev_info { | 342 | struct rvt_dev_info { |
@@ -483,6 +485,23 @@ static inline struct rvt_qp *rvt_lookup_qpn(struct rvt_dev_info *rdi, | |||
483 | return qp; | 485 | return qp; |
484 | } | 486 | } |
485 | 487 | ||
488 | /** | ||
489 | * rvt_mod_retry_timer - mod a retry timer | ||
490 | * @qp - the QP | ||
491 | * Modify a potentially already running retry timer | ||
492 | */ | ||
493 | static inline void rvt_mod_retry_timer(struct rvt_qp *qp) | ||
494 | { | ||
495 | struct ib_qp *ibqp = &qp->ibqp; | ||
496 | struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device); | ||
497 | |||
498 | lockdep_assert_held(&qp->s_lock); | ||
499 | qp->s_flags |= RVT_S_TIMER; | ||
500 | /* 4.096 usec. * (1 << qp->timeout) */ | ||
501 | mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies + | ||
502 | rdi->busy_jiffies); | ||
503 | } | ||
504 | |||
486 | struct rvt_dev_info *rvt_alloc_device(size_t size, int nports); | 505 | struct rvt_dev_info *rvt_alloc_device(size_t size, int nports); |
487 | void rvt_dealloc_device(struct rvt_dev_info *rdi); | 506 | void rvt_dealloc_device(struct rvt_dev_info *rdi); |
488 | int rvt_register_device(struct rvt_dev_info *rvd); | 507 | int rvt_register_device(struct rvt_dev_info *rvd); |
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h index a92e7dcfb5f5..0b1cbffb967c 100644 --- a/include/rdma/rdmavt_qp.h +++ b/include/rdma/rdmavt_qp.h | |||
@@ -370,6 +370,7 @@ struct rvt_qp { | |||
370 | 370 | ||
371 | struct rvt_sge_state s_ack_rdma_sge; | 371 | struct rvt_sge_state s_ack_rdma_sge; |
372 | struct timer_list s_timer; | 372 | struct timer_list s_timer; |
373 | struct hrtimer s_rnr_timer; | ||
373 | 374 | ||
374 | atomic_t local_ops_pending; /* number of fast_reg/local_inv reqs */ | 375 | atomic_t local_ops_pending; /* number of fast_reg/local_inv reqs */ |
375 | 376 | ||
@@ -641,5 +642,10 @@ struct rvt_dev_info; | |||
641 | void rvt_comm_est(struct rvt_qp *qp); | 642 | void rvt_comm_est(struct rvt_qp *qp); |
642 | int rvt_error_qp(struct rvt_qp *qp, enum ib_wc_status err); | 643 | int rvt_error_qp(struct rvt_qp *qp, enum ib_wc_status err); |
643 | void rvt_rc_error(struct rvt_qp *qp, enum ib_wc_status err); | 644 | void rvt_rc_error(struct rvt_qp *qp, enum ib_wc_status err); |
645 | enum hrtimer_restart rvt_rc_rnr_retry(struct hrtimer *t); | ||
646 | void rvt_add_rnr_timer(struct rvt_qp *qp, u32 aeth); | ||
647 | void rvt_del_timers_sync(struct rvt_qp *qp); | ||
648 | void rvt_stop_rc_timers(struct rvt_qp *qp); | ||
649 | void rvt_add_retry_timer(struct rvt_qp *qp); | ||
644 | 650 | ||
645 | #endif /* DEF_RDMAVT_INCQP_H */ | 651 | #endif /* DEF_RDMAVT_INCQP_H */ |